[Qemu-devel] [Bug 1649040] [NEW] Ubuntu 16.04.1 Grub Splash Doesn't Appear

2016-12-11 Thread LPNow
Public bug reported:

My Specs:

Slackware 14.2 x86_64 > Host
QEMU 2.7.0

Ubuntu 16.04.1 x86_64 > Guest

Start options for Ubuntu:

qemu-system-x86_64 -drive format=raw,file=ubuntu.img \
-cpu host \
--enable-kvm \
-smp 2 \
-m 4096 \
-vga vmware \
-soundhw ac97 \
-usbdevice tablet \
-rtc base=localtime \
-usbdevice host:0781:5575

I've started Ubuntu around 6-8 times, and I have only see the Grub Boot
Splash appear twice, so pretty much without fail it typically boots past
the grub splash and automatically boots...

These are the /etc/default/grub settings; (I only changed these options
GRUB_TIMEOUT=15 and GRUB_GFXMODE=1440x900)

# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.
# For full documentation of the options in this file, see:
#   info -f grub -n 'Simple configuration'

GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=15
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""

# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"

# Uncomment to disable graphical terminal (grub-pc only)
#GRUB_TERMINAL=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
GRUB_GFXMODE=1440x900

# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true

# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY="true"

# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"

** Affects: qemu
 Importance: Undecided
 Status: New

** Description changed:

  My Specs:
  
  Slackware 14.2 x86_64 > Host
- QEMU 2.7.0 
+ QEMU 2.7.0
  
- Ubuntu 16.04.1 > Guest
+ Ubuntu 16.04.1 x86_64 > Guest
  
  Start options for Ubuntu:
  
  qemu-system-x86_64 -drive format=raw,file=ubuntu.img \
  -cpu host \
  --enable-kvm \
  -smp 2 \
  -m 4096 \
  -vga vmware \
  -soundhw ac97 \
  -usbdevice tablet \
  -rtc base=localtime \
  -usbdevice host:0781:5575
  
- 
  I've started Ubuntu around 6-8 times, and I have only see the Grub Boot
  Splash appear twice, so pretty much without fail it typically boots past
  the grub splash and automatically boots...
  
- 
- These are the /etc/default/grub settings; (I only changed these options 
GRUB_TIMEOUT=15 and GRUB_GFXMODE=1440x900)
- 
+ These are the /etc/default/grub settings; (I only changed these options
+ GRUB_TIMEOUT=15 and GRUB_GFXMODE=1440x900)
  
  # If you change this file, run 'update-grub' afterwards to update
  # /boot/grub/grub.cfg.
  # For full documentation of the options in this file, see:
  #   info -f grub -n 'Simple configuration'
  
  GRUB_DEFAULT=0
  GRUB_HIDDEN_TIMEOUT=0
  GRUB_HIDDEN_TIMEOUT_QUIET=true
  GRUB_TIMEOUT=15
  GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
  GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
  GRUB_CMDLINE_LINUX=""
  
  # Uncomment to enable BadRAM filtering, modify to suit your needs
  # This works with Linux (no patch required) and with any kernel that obtains
  # the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
  #GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
  
  # Uncomment to disable graphical terminal (grub-pc only)
  #GRUB_TERMINAL=console
  
  # The resolution used on graphical terminal
  # note that you can use only modes which your graphic card supports via VBE
  # you can see them in real GRUB with the command `vbeinfo'
  GRUB_GFXMODE=1440x900
  
  # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
  #GRUB_DISABLE_LINUX_UUID=true
  
  # Uncomment to disable generation of recovery mode menu entries
  #GRUB_DISABLE_RECOVERY="true"
  
  # Uncomment to get a beep at grub start
  #GRUB_INIT_TUNE="480 440 1"

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

Title:
  Ubuntu 16.04.1 Grub Splash Doesn't Appear

Status in QEMU:
  New

Bug description:
  My Specs:

  Slackware 14.2 x86_64 > Host
  QEMU 2.7.0

  Ubuntu 16.04.1 x86_64 > Guest

  Start options for Ubuntu:

  qemu-system-x86_64 -drive format=raw,file=ubuntu.img \
  -cpu host \
  --enable-kvm \
  -smp 2 \
  -m 4096 \
  -vga vmware \
  -soundhw ac97 \
  -usbdevice tablet \
  -rtc base=localtime \
  -usbdevice host:0781:5575

  I've started Ubuntu around 6-8 times, and I have only see the Grub
  Boot Splash appear twice, so pretty much without fail it typically
  boots past the grub splash and automatically boots...

  These are the /etc/default/grub settings; (I only changed these
  options GRUB_TIMEOUT=15 and GRUB_GFXMODE=144

[Qemu-devel] [Bug 1649042] [NEW] Ubuntu 16.04.1 LightDM Resolution Not Correct

2016-12-11 Thread LPNow
Public bug reported:

My Specs:

Slackware 14.2 x86_64 > Host
Nvidia GPU GTX660M
nvidia-driver-352.63
QEMU 2.7.0

Ubuntu 16.04.1 x86_64 > Guest
Unity
Xorg nouveau - 1:1.0.12-1build2

These are the startup options for Ubuntu:

qemu-system-x86_64 -drive format=raw,file=ubuntu.img \
-cpu host \
--enable-kvm \
-smp 2 \
-m 4096 \
-vga vmware \
-soundhw ac97 \
-usbdevice tablet \
-rtc base=localtime \
-usbdevice host:0781:5575

Unity desktop resolution set for 1440x900.

I noticed when I come to the login screen to enter my password the
LightDM resolution fills my entire desktop.

I searched online and found this solution;

cp ~/.config/monitor.xml /var/lib/lightdm/.config

For now I'm assuming this step should not be needed and the resolution
should be correctly detected and set?

** Affects: qemu
 Importance: Undecided
 Status: New

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

Title:
  Ubuntu 16.04.1 LightDM Resolution Not Correct

Status in QEMU:
  New

Bug description:
  My Specs:

  Slackware 14.2 x86_64 > Host
  Nvidia GPU GTX660M
  nvidia-driver-352.63
  QEMU 2.7.0

  Ubuntu 16.04.1 x86_64 > Guest
  Unity
  Xorg nouveau - 1:1.0.12-1build2

  These are the startup options for Ubuntu:

  qemu-system-x86_64 -drive format=raw,file=ubuntu.img \
  -cpu host \
  --enable-kvm \
  -smp 2 \
  -m 4096 \
  -vga vmware \
  -soundhw ac97 \
  -usbdevice tablet \
  -rtc base=localtime \
  -usbdevice host:0781:5575

  Unity desktop resolution set for 1440x900.

  I noticed when I come to the login screen to enter my password the
  LightDM resolution fills my entire desktop.

  I searched online and found this solution;

  cp ~/.config/monitor.xml /var/lib/lightdm/.config

  For now I'm assuming this step should not be needed and the resolution
  should be correctly detected and set?

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



Re: [Qemu-devel] [for-2.9 2/5] pseries: Stubs for HPT resizing

2016-12-11 Thread David Gibson
On Fri, Dec 09, 2016 at 11:08:02AM -0600, Michael Roth wrote:
> Quoting David Gibson (2016-12-08 20:23:11)
> > This introduces stub implementations of the H_RESIZE_HPT_PREPARE and
> > H_RESIZE_HPT_COMMIT hypercalls which we hope to add in a PAPR
> > extension to allow run time resizing of a guest's hash page table.  It
> > also adds a new machine property for controlling whether this new
> > facility is available, and logic to check that against availability
> > with KVM (only supported with KVM PR for now).
> > 
> > Finally, it adds a new string to the hypertas property in the device
> > tree, advertising to the guest the availability of the HPT resizing
> > hypercalls.  This is a tentative suggested value, and would need to be
> > standardized by PAPR before being merged.
> > 
> > Signed-off-by: David Gibson 
> > ---
> >  hw/ppc/spapr.c | 66 
> > ++
> >  hw/ppc/spapr_hcall.c   | 36 +++
> >  hw/ppc/trace-events|  2 ++
> >  include/hw/ppc/spapr.h | 11 +
> >  target-ppc/kvm.c   | 26 
> >  target-ppc/kvm_ppc.h   |  5 
> >  6 files changed, 146 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index 0f25e83..ecb0822 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -760,6 +760,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, 
> > void *fdt)
> >  if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> >  add_str(hypertas, "hcall-multi-tce");
> >  }
> > +
> > +if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
> > +add_str(hypertas, "hcall-hpt-resize");
> > +}
> > +
> >  _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions",
> >   hypertas->str, hypertas->len));
> >  g_string_free(hypertas, TRUE);
> > @@ -1839,11 +1844,31 @@ static void ppc_spapr_init(MachineState *machine)
> >  long load_limit, fw_size;
> >  char *filename;
> >  int smt = kvmppc_smt_threads();
> > +Error *resize_hpt_err = NULL;
> > 
> >  msi_nonbroken = true;
> > 
> >  QLIST_INIT(&spapr->phbs);
> > 
> > +/* Check HPT resizing availability */
> > +kvmppc_check_papr_resize_hpt(&resize_hpt_err);
> > +if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) {
> > +if (resize_hpt_err) {
> > +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
> > +error_free(resize_hpt_err);
> > +resize_hpt_err = NULL;
> > +} else {
> > +spapr->resize_hpt = smc->resize_hpt_default;
> > +}
> > +}
> > +
> > +assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT);
> > +
> > +if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && 
> > resize_hpt_err) {
> > +error_report_err(resize_hpt_err);
> > +exit(1);
> > +}
> 
> I'm also a bit confused by this. Aren't semantics that HPT_ENABLED will allow
> a fallback to non-resizable HPTs if the feature isn't available (whereas
> HPT_REQUIRED won't)? I don't understand how such a fallback can ever be 
> reached
> with this check in place.

resize-hpt=enabled means we'll fall back if the guest doesn't support
it.  An error here means the _host_ can't support it.  I think not
falling back is the better option in this case - if you've explicitly
tried to enable it from it should be available or fail.  In particular
this will make it safer for migrations where the source is already
using hpt resizing.

> > +
> >  /* Allocate RMA if necessary */
> >  rma_alloc_size = kvmppc_alloc_rma(&rma);
> > 
> > @@ -2236,6 +2261,40 @@ static void spapr_set_modern_hotplug_events(Object 
> > *obj, bool value,
> >  spapr->use_hotplug_event_source = value;
> >  }
> > 
> > +static char *spapr_get_resize_hpt(Object *obj, Error **errp)
> > +{
> > +sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
> > +
> > +switch (spapr->resize_hpt) {
> > +case SPAPR_RESIZE_HPT_DEFAULT:
> > +return g_strdup("default");
> > +case SPAPR_RESIZE_HPT_DISABLED:
> > +return g_strdup("disabled");
> > +case SPAPR_RESIZE_HPT_ENABLED:
> > +return g_strdup("enabled");
> > +case SPAPR_RESIZE_HPT_REQUIRED:
> > +return g_strdup("required");
> > +}
> > +assert(0);
> > +}
> > +
> > +static void spapr_set_resize_hpt(Object *obj, const char *value, Error 
> > **errp)
> > +{
> > +sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
> > +
> > +if (strcmp(value, "default") == 0) {
> > +spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT;
> > +} else if (strcmp(value, "disabled") == 0) {
> > +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
> > +} else if (strcmp(value, "enabled") == 0) {
> > +spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED;
> > +} else if (strcmp(value, "required") == 0) {
> > +spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED;
> > +} else {
> > +error_setg(errp, "Bad value for \"resize-hpt\" property");
> > +}

[Qemu-devel] [PATCH v6 04/10] tcg-mips: Add bswap32u and bswap64

2016-12-11 Thread Jin Guojie
Without the mips32r2 instructions to perform swapping, bswap is quite large,
dominating the size of each reverse-endian qemu_ld/qemu_st operation.

Create two subroutines in the prologue block.  The subroutines require extra
reserved registers (TCG_TMP[2, 3]).  Using these within qemu_ld means that
we need not place additional restrictions on the qemu_ld outputs.

Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.inc.c | 102 --
 1 file changed, 99 insertions(+), 3 deletions(-)

diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 2d91d0c..ec139cd 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -125,6 +125,8 @@ static const TCGReg tcg_target_call_oarg_regs[2] = {
 
 static tcg_insn_unit *tb_ret_addr;
 static tcg_insn_unit *bswap32_addr;
+static tcg_insn_unit *bswap32u_addr;
+static tcg_insn_unit *bswap64_addr;
 
 static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
 {
@@ -622,7 +624,10 @@ static void tcg_out_bswap32u(TCGContext *s, TCGReg ret, 
TCGReg arg)
 tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
 tcg_out_dsrl(s, ret, ret, 32);
 } else {
-abort();
+tcg_out_bswap_subr(s, bswap32u_addr);
+/* delay slot -- never omit the insn, like tcg_out_mov might.  */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
+tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
 }
 }
 
@@ -632,7 +637,10 @@ static void tcg_out_bswap64(TCGContext *s, TCGReg ret, 
TCGReg arg)
 tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
 tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
 } else {
-abort();
+tcg_out_bswap_subr(s, bswap64_addr);
+/* delay slot -- never omit the insn, like tcg_out_mov might.  */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
+tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
 }
 }
 
@@ -2279,7 +2287,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 return;
 }
 
-/* Bswap subroutine: Input in TCG_TMP0, output in TCG_TMP3;
+/* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
clobbers TCG_TMP1, TCG_TMP2.  */
 
 /*
@@ -2305,6 +2313,94 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
 /* t3 = dcba -- delay slot */
 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+
+if (TCG_TARGET_REG_BITS == 32) {
+return;
+}
+
+/*
+ * bswap32u -- unsigned 32-bit swap.  a0 = abcd.
+ */
+bswap32u_addr = align_code_ptr(s);
+/* t1 = ()000d */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff);
+/* t3 = 000a */
+tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24);
+/* t1 = ()d000 */
+tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
+/* t2 = 00c0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
+/* t3 = d00a */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+/* t1 = 0abc */
+tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
+/* t2 = 0c00 */
+tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
+/* t1 = 00b0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
+/* t3 = dc0a */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
+tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
+/* t3 = dcba -- delay slot */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+
+/*
+ * bswap64 -- 64-bit swap.  a0 = abcdefgh
+ */
+bswap64_addr = align_code_ptr(s);
+/* t3 = h000 */
+tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56);
+/* t1 = 000a */
+tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56);
+
+/* t2 = 00g0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
+/* t3 = h00a */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+/* t1 = 0abc */
+tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40);
+/* t2 = 0g00 */
+tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
+/* t1 = 00b0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
+
+/* t3 = hg0a */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
+/* t2 = abcd */
+tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32);
+/* t3 = hgba */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+
+/* t1 = 00c0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00);
+/* t2 = 000d */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff);
+/* t1 = 0c00 */
+tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8);
+/* t2 = d000 */
+tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24);
+
+/* t3 = hg000cba */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+/* t1 = 00abcdef */
+tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 1

[Qemu-devel] [PATCH v6 05/10] tcg-mips: Adjust move functions for mips64

2016-12-11 Thread Jin Guojie
tcg_out_mov: using OPC_OR as most mips assemblers do;
tcg_out_movi: extended to 64-bit immediate.

Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.inc.c | 34 +-
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index ec139cd..18368f0 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -544,23 +544,39 @@ static inline void tcg_out_mov(TCGContext *s, TCGType 
type,
 {
 /* Simple reg-reg move, optimising out the 'do nothing' case */
 if (ret != arg) {
-tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
+tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO);
 }
 }
 
-static inline void tcg_out_movi(TCGContext *s, TCGType type,
-TCGReg reg, tcg_target_long arg)
+static void tcg_out_movi(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
 {
+if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
+arg = (int32_t)arg;
+}
 if (arg == (int16_t)arg) {
-tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
-} else if (arg == (uint16_t)arg) {
-tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
+tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
+return;
+}
+if (arg == (uint16_t)arg) {
+tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
+return;
+}
+if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) {
+tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
 } else {
-tcg_out_opc_imm(s, OPC_LUI, reg, TCG_REG_ZERO, arg >> 16);
-if (arg & 0x) {
-tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0x);
+tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1);
+if (arg & 0xull) {
+tcg_out_dsll(s, ret, ret, 16);
+tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16);
+tcg_out_dsll(s, ret, ret, 16);
+} else {
+tcg_out_dsll(s, ret, ret, 32);
 }
 }
+if (arg & 0x) {
+tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0x);
+}
 }
 
 static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
-- 
2.1.0





[Qemu-devel] [PATCH v6 01/10] tcg-mips: Move bswap code to a subroutine

2016-12-11 Thread Jin Guojie
Without the mips32r2 instructions to perform swapping, bswap is quite large,
dominating the size of each reverse-endian qemu_ld/qemu_st operation.

Create a subroutine in the prologue block.  The subroutine requires extra
reserved registers (TCG_TMP[2, 3]).  Using these within qemu_ld means that
we need not place additional restrictions on the qemu_ld outputs.

Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.h |   2 +-
 tcg/mips/tcg-target.inc.c | 207 ++
 2 files changed, 139 insertions(+), 70 deletions(-)

diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 3aeac87..a6871fb 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -117,11 +117,11 @@ extern bool use_mips32r2_instructions;
 #define TCG_TARGET_HAS_muls2_i32(!use_mips32r6_instructions)
 #define TCG_TARGET_HAS_muluh_i321
 #define TCG_TARGET_HAS_mulsh_i321
+#define TCG_TARGET_HAS_bswap32_i32  1
 
 /* optional instructions detected at runtime */
 #define TCG_TARGET_HAS_movcond_i32  use_movnz_instructions
 #define TCG_TARGET_HAS_bswap16_i32  use_mips32r2_instructions
-#define TCG_TARGET_HAS_bswap32_i32  use_mips32r2_instructions
 #define TCG_TARGET_HAS_deposit_i32  use_mips32r2_instructions
 #define TCG_TARGET_HAS_ext8s_i32use_mips32r2_instructions
 #define TCG_TARGET_HAS_ext16s_i32   use_mips32r2_instructions
diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index abce602..2b116ea 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -74,6 +74,8 @@ static const char * const 
tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 
 #define TCG_TMP0  TCG_REG_AT
 #define TCG_TMP1  TCG_REG_T9
+#define TCG_TMP2  TCG_REG_T8
+#define TCG_TMP3  TCG_REG_T7
 
 /* check if we really need so many registers :P */
 static const int tcg_target_reg_alloc_order[] = {
@@ -122,6 +124,7 @@ static const TCGReg tcg_target_call_oarg_regs[2] = {
 };
 
 static tcg_insn_unit *tb_ret_addr;
+static tcg_insn_unit *bswap32_addr;
 
 static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
 {
@@ -177,12 +180,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, 
const char **pct_str)
 ct->ct |= TCG_CT_REG;
 tcg_regset_set(ct->u.regs, 0x);
 break;
-case 'L': /* qemu_ld output arg constraint */
-ct->ct |= TCG_CT_REG;
-tcg_regset_set(ct->u.regs, 0x);
-tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
-break;
-case 'l': /* qemu_ld input arg constraint */
+case 'L': /* qemu_ld input arg constraint */
 ct->ct |= TCG_CT_REG;
 tcg_regset_set(ct->u.regs, 0x);
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
@@ -513,29 +511,22 @@ static inline void tcg_out_bswap16s(TCGContext *s, TCGReg 
ret, TCGReg arg)
 }
 }
 
-static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
+static void tcg_out_bswap_subr(TCGContext *s, tcg_insn_unit *sub)
+{
+bool ok = tcg_out_opc_jmp(s, OPC_JAL, sub);
+tcg_debug_assert(ok);
+}
+
+static void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
 {
 if (use_mips32r2_instructions) {
 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
 tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
 } else {
-/* ret and arg must be different and can't be register at */
-if (ret == arg || ret == TCG_TMP0 || arg == TCG_TMP0) {
-tcg_abort();
-}
-
-tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
-
-tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 24);
-tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
-
-tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, arg, 0xff00);
-tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8);
-tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
-
-tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
-tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0xff00);
-tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
+tcg_out_bswap_subr(s, bswap32_addr);
+/* delay slot -- never omit the insn, like tcg_out_mov might.  */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
+tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
 }
 }
 
@@ -1044,7 +1035,7 @@ static int tcg_out_call_iarg_reg2(TCGContext *s, int i, 
TCGReg al, TCGReg ah)
 }
 
 /* Perform the tlb comparison operation.  The complete host address is
-   placed in BASE.  Clobbers AT, T0, A0.  */
+   placed in BASE.  Clobbers TMP0, TMP1, A0.  */
 static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
  TCGReg addrh, TCGMemOpIdx oi,
  tcg_insn_unit *label_ptr[2], bool is_load)
@@ -1227,46 +1218,72 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 }
 #endif
 
-static voi

[Qemu-devel] [PATCH v6 02/10] tcg-mips: Add mips64 opcodes

2016-12-11 Thread Jin Guojie
Since the mips manual tables are in octal, reorg all of the opcodes
into that format for clarity.  Note that the 64-bit opcodes are as
yet unused.

Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.inc.c | 193 --
 1 file changed, 118 insertions(+), 75 deletions(-)

diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 2b116ea..fb84ea5 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -254,81 +254,118 @@ static inline int tcg_target_const_match(tcg_target_long 
val, TCGType type,
 
 /* instruction opcodes */
 typedef enum {
-OPC_J= 0x02 << 26,
-OPC_JAL  = 0x03 << 26,
-OPC_BEQ  = 0x04 << 26,
-OPC_BNE  = 0x05 << 26,
-OPC_BLEZ = 0x06 << 26,
-OPC_BGTZ = 0x07 << 26,
-OPC_ADDIU= 0x09 << 26,
-OPC_SLTI = 0x0A << 26,
-OPC_SLTIU= 0x0B << 26,
-OPC_ANDI = 0x0C << 26,
-OPC_ORI  = 0x0D << 26,
-OPC_XORI = 0x0E << 26,
-OPC_LUI  = 0x0F << 26,
-OPC_LB   = 0x20 << 26,
-OPC_LH   = 0x21 << 26,
-OPC_LW   = 0x23 << 26,
-OPC_LBU  = 0x24 << 26,
-OPC_LHU  = 0x25 << 26,
-OPC_LWU  = 0x27 << 26,
-OPC_SB   = 0x28 << 26,
-OPC_SH   = 0x29 << 26,
-OPC_SW   = 0x2B << 26,
-
-OPC_SPECIAL  = 0x00 << 26,
-OPC_SLL  = OPC_SPECIAL | 0x00,
-OPC_SRL  = OPC_SPECIAL | 0x02,
-OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02,
-OPC_SRA  = OPC_SPECIAL | 0x03,
-OPC_SLLV = OPC_SPECIAL | 0x04,
-OPC_SRLV = OPC_SPECIAL | 0x06,
-OPC_ROTRV= OPC_SPECIAL | (0x01 <<  6) | 0x06,
-OPC_SRAV = OPC_SPECIAL | 0x07,
-OPC_JR_R5= OPC_SPECIAL | 0x08,
-OPC_JALR = OPC_SPECIAL | 0x09,
-OPC_MOVZ = OPC_SPECIAL | 0x0A,
-OPC_MOVN = OPC_SPECIAL | 0x0B,
-OPC_SYNC = OPC_SPECIAL | 0x0F,
-OPC_MFHI = OPC_SPECIAL | 0x10,
-OPC_MFLO = OPC_SPECIAL | 0x12,
-OPC_MULT = OPC_SPECIAL | 0x18,
-OPC_MUL_R6   = OPC_SPECIAL | (0x02 <<  6) | 0x18,
-OPC_MUH  = OPC_SPECIAL | (0x03 <<  6) | 0x18,
-OPC_MULTU= OPC_SPECIAL | 0x19,
-OPC_MULU = OPC_SPECIAL | (0x02 <<  6) | 0x19,
-OPC_MUHU = OPC_SPECIAL | (0x03 <<  6) | 0x19,
-OPC_DIV  = OPC_SPECIAL | 0x1A,
-OPC_DIV_R6   = OPC_SPECIAL | (0x02 <<  6) | 0x1A,
-OPC_MOD  = OPC_SPECIAL | (0x03 <<  6) | 0x1A,
-OPC_DIVU = OPC_SPECIAL | 0x1B,
-OPC_DIVU_R6  = OPC_SPECIAL | (0x02 <<  6) | 0x1B,
-OPC_MODU = OPC_SPECIAL | (0x03 <<  6) | 0x1B,
-OPC_ADDU = OPC_SPECIAL | 0x21,
-OPC_SUBU = OPC_SPECIAL | 0x23,
-OPC_AND  = OPC_SPECIAL | 0x24,
-OPC_OR   = OPC_SPECIAL | 0x25,
-OPC_XOR  = OPC_SPECIAL | 0x26,
-OPC_NOR  = OPC_SPECIAL | 0x27,
-OPC_SLT  = OPC_SPECIAL | 0x2A,
-OPC_SLTU = OPC_SPECIAL | 0x2B,
-OPC_SELEQZ   = OPC_SPECIAL | 0x35,
-OPC_SELNEZ   = OPC_SPECIAL | 0x37,
-
-OPC_REGIMM   = 0x01 << 26,
-OPC_BLTZ = OPC_REGIMM | (0x00 << 16),
-OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
-
-OPC_SPECIAL2 = 0x1c << 26,
-OPC_MUL_R5   = OPC_SPECIAL2 | 0x002,
-
-OPC_SPECIAL3 = 0x1f << 26,
-OPC_EXT  = OPC_SPECIAL3 | 0x000,
-OPC_INS  = OPC_SPECIAL3 | 0x004,
-OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
-OPC_SEB  = OPC_SPECIAL3 | 0x420,
-OPC_SEH  = OPC_SPECIAL3 | 0x620,
+OPC_J= 002 << 26,
+OPC_JAL  = 003 << 26,
+OPC_BEQ  = 004 << 26,
+OPC_BNE  = 005 << 26,
+OPC_BLEZ = 006 << 26,
+OPC_BGTZ = 007 << 26,
+OPC_ADDIU= 011 << 26,
+OPC_SLTI = 012 << 26,
+OPC_SLTIU= 013 << 26,
+OPC_ANDI = 014 << 26,
+OPC_ORI  = 015 << 26,
+OPC_XORI = 016 << 26,
+OPC_LUI  = 017 << 26,
+OPC_DADDIU   = 031 << 26,
+OPC_LB   = 040 << 26,
+OPC_LH   = 041 << 26,
+OPC_LW   = 043 << 26,
+OPC_LBU  = 044 << 26,
+OPC_LHU  = 045 << 26,
+OPC_LWU  = 047 << 26,
+OPC_SB   = 050 << 26,
+OPC_SH   = 051 << 26,
+OPC_SW   = 053 << 26,
+OPC_LD   = 067 << 26,
+OPC_SD   = 077 << 26,
+
+OPC_SPECIAL  = 000 << 26,
+OPC_SLL  = OPC_SPECIAL | 000,
+OPC_SRL  = OPC_SPECIAL | 002,
+OPC_ROTR = OPC_SPECIAL | 002 | (1 << 21),
+OPC_SRA  = OPC_SPECIAL | 003,
+OPC_SLLV = OPC_SPECIAL | 004,
+OPC_SRLV = OPC_SPECIAL | 006,
+OPC_ROTRV= OPC_SPECIAL | 006 | 0100,
+OPC_SRAV = OPC_SPECIAL | 007,
+OPC_JR_R5= OPC_SPECIAL | 010,
+OPC_JALR = OPC_SPECIAL | 011,
+OPC_MOVZ = OPC_SPECIAL | 012,
+OPC_MOVN = OPC_SPECIAL | 013,
+OPC_SYNC = OPC_SPECIAL | 017,
+OPC_MFHI = OPC_SPECIAL | 020,
+OPC_MFLO = OPC_SPECIAL | 022,
+OPC_DSLLV= OPC_SPECIAL | 024,
+

[Qemu-devel] [PATCH v6 03/10] tcg-mips: Support 64-bit opcodes

2016-12-11 Thread Jin Guojie
Bulk patch adding 64-bit opcodes into tcg_out_op.  Note that
mips64 is as yet neither complete nor enabled.

Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.h |  41 ++
 tcg/mips/tcg-target.inc.c | 322 --
 2 files changed, 353 insertions(+), 10 deletions(-)

diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index a6871fb..4b7d3ae 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -27,6 +27,7 @@
 #ifndef MIPS_TCG_TARGET_H
 #define MIPS_TCG_TARGET_H
 
+#define TCG_TARGET_REG_BITS 32
 #define TCG_TARGET_INSN_UNIT_SIZE 4
 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 16
 #define TCG_TARGET_NB_REGS 32
@@ -119,6 +120,29 @@ extern bool use_mips32r2_instructions;
 #define TCG_TARGET_HAS_mulsh_i321
 #define TCG_TARGET_HAS_bswap32_i32  1
 
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_add2_i32 0
+#define TCG_TARGET_HAS_sub2_i32 0
+#define TCG_TARGET_HAS_extrl_i64_i321
+#define TCG_TARGET_HAS_extrh_i64_i321
+#define TCG_TARGET_HAS_div_i64  1
+#define TCG_TARGET_HAS_rem_i64  1
+#define TCG_TARGET_HAS_not_i64  1
+#define TCG_TARGET_HAS_nor_i64  1
+#define TCG_TARGET_HAS_andc_i64 0
+#define TCG_TARGET_HAS_orc_i64  0
+#define TCG_TARGET_HAS_eqv_i64  0
+#define TCG_TARGET_HAS_nand_i64 0
+#define TCG_TARGET_HAS_add2_i64 0
+#define TCG_TARGET_HAS_sub2_i64 0
+#define TCG_TARGET_HAS_mulu2_i64(!use_mips32r6_instructions)
+#define TCG_TARGET_HAS_muls2_i64(!use_mips32r6_instructions)
+#define TCG_TARGET_HAS_muluh_i641
+#define TCG_TARGET_HAS_mulsh_i641
+#define TCG_TARGET_HAS_ext32s_i64   1
+#define TCG_TARGET_HAS_ext32u_i64   1
+#endif
+
 /* optional instructions detected at runtime */
 #define TCG_TARGET_HAS_movcond_i32  use_movnz_instructions
 #define TCG_TARGET_HAS_bswap16_i32  use_mips32r2_instructions
@@ -127,11 +151,28 @@ extern bool use_mips32r2_instructions;
 #define TCG_TARGET_HAS_ext16s_i32   use_mips32r2_instructions
 #define TCG_TARGET_HAS_rot_i32  use_mips32r2_instructions
 
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_movcond_i64  use_movnz_instructions
+#define TCG_TARGET_HAS_bswap16_i64  use_mips32r2_instructions
+#define TCG_TARGET_HAS_bswap32_i64  use_mips32r2_instructions
+#define TCG_TARGET_HAS_bswap64_i64  use_mips32r2_instructions
+#define TCG_TARGET_HAS_deposit_i64  use_mips32r2_instructions
+#define TCG_TARGET_HAS_ext8s_i64use_mips32r2_instructions
+#define TCG_TARGET_HAS_ext16s_i64   use_mips32r2_instructions
+#define TCG_TARGET_HAS_rot_i64  use_mips32r2_instructions
+#endif
+
 /* optional instructions automatically implemented */
 #define TCG_TARGET_HAS_neg_i32  0 /* sub  rd, zero, rt   */
 #define TCG_TARGET_HAS_ext8u_i320 /* andi rt, rs, 0xff   */
 #define TCG_TARGET_HAS_ext16u_i32   0 /* andi rt, rs, 0x */
 
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_neg_i64  0 /* sub  rd, zero, rt   */
+#define TCG_TARGET_HAS_ext8u_i640 /* andi rt, rs, 0xff   */
+#define TCG_TARGET_HAS_ext16u_i64   0 /* andi rt, rs, 0x */
+#endif
+
 #ifdef __OpenBSD__
 #include 
 #else
diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index fb84ea5..2d91d0c 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -437,6 +437,21 @@ static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn 
opc, TCGReg rt,
 tcg_out32(s, inst);
 }
 
+static inline void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
+MIPSInsn oph, TCGReg rt, TCGReg rs,
+int msb, int lsb)
+{
+if (lsb >= 32) {
+opc = oph;
+msb -= 32;
+lsb -= 32;
+} else if (msb >= 32) {
+opc = opm;
+msb -= 32;
+}
+tcg_out_opc_bf(s, opc, rt, rs, msb, lsb);
+}
+
 /*
  * Type branch
  */
@@ -467,6 +482,18 @@ static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn 
opc,
 
 }
 
+static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2,
+ TCGReg rd, TCGReg rt, TCGArg sa)
+{
+int32_t inst;
+
+inst = (sa & 32 ? opc2 : opc1);
+inst |= (rt & 0x1F) << 16;
+inst |= (rd & 0x1F) << 11;
+inst |= (sa & 0x1F) <<  6;
+tcg_out32(s, inst);
+}
+
 /*
  * Type jump.
  * Returns true if the branch was in range and the insn was emitted.
@@ -495,6 +522,21 @@ static inline void tcg_out_nop(TCGContext *s)
 tcg_out32(s, 0);
 }
 
+static inline void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
+{
+tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
+}
+
+static inline void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
+{
+tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSR

[Qemu-devel] [PATCH v6 08/10] tcg-mips: Add tcg unwind info

2016-12-11 Thread Jin Guojie
Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.inc.c | 44 
 1 file changed, 44 insertions(+)

diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 9e24662..b7e2586 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -2465,3 +2465,47 @@ void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t 
addr)
 atomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2));
 flush_icache_range(jmp_addr, jmp_addr + 4);
 }
+
+typedef struct {
+DebugFrameHeader h;
+uint8_t fde_def_cfa[4];
+uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
+} DebugFrame;
+
+#define ELF_HOST_MACHINE EM_MIPS
+/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
+   which is good because they're really quite complicated for MIPS.  */
+
+static const DebugFrame debug_frame = {
+.h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
+.h.cie.id = -1,
+.h.cie.version = 1,
+.h.cie.code_align = 1,
+.h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
+.h.cie.return_column = TCG_REG_RA,
+
+/* Total FDE size does not include the "len" member.  */
+.h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
+
+.fde_def_cfa = {
+12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
+(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
+(FRAME_SIZE >> 7)
+},
+.fde_reg_ofs = {
+0x80 + 16, 9,   /* DW_CFA_offset, s0, -72 */
+0x80 + 17, 8,   /* DW_CFA_offset, s2, -64 */
+0x80 + 18, 7,   /* DW_CFA_offset, s3, -56 */
+0x80 + 19, 6,   /* DW_CFA_offset, s4, -48 */
+0x80 + 20, 5,   /* DW_CFA_offset, s5, -40 */
+0x80 + 21, 4,   /* DW_CFA_offset, s6, -32 */
+0x80 + 22, 3,   /* DW_CFA_offset, s7, -24 */
+0x80 + 30, 2,   /* DW_CFA_offset, s8, -16 */
+0x80 + 31, 1,   /* DW_CFA_offset, ra,  -8 */
+}
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
-- 
2.1.0





[Qemu-devel] [PATCH v6 00/10] tcg mips64 and mips r6 improvements

2016-12-11 Thread Jin Guojie
Changes in v6:
  * Update against master(v2.8.0-rc3)
  * Fix two bugs according to Richard Henderson's review comments
(1) mask: extend TARGET_PAGE_MASK to the proper type
(2) zero-extend the guest address, not the address loaded from CMP_OFF
  * MIPS R6: tested successfully on a qemu mipsel64r6 host (emulating I6400)
- Debian amd64 with qemu-system-x86_64

Changes in v5:
  * Update against master(v2.8.0-rc2)
  * Fix a bug: 64-bit big-endian guests hang on mips64 little-endian
  hosts, and vice versa. This bug was first introduced in v2 patch,
  due to obvious misuse of ret/arg registers in tcg_out_bswap64().

tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
  - tcg_out_opc_reg(s, OPC_DSHD, ret, 0, arg);
  + tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);

  * Fix a style problem: checkpatch.pl forbids 'extern' to be used in .c.

  ERROR: externs should be avoided in .c files
  #28: FILE: tcg/mips/tcg-target.inc.c:39:
  +extern int link_error(void);

  Simply comment the type identifier to pass the check.

  * Tested successfully on following machines:
  
| HOST| qemu-system | Debian ISO  |
|-|
| mips 32 le  |i386 |i386 |
| mips 32 le  |x86_64   |i386 |
| mips 32 le  |x86_64   |amd64|
| mips 64 le  |i386 |i386 |
| mips 64 le  |x86_64   |i386 |
| mips 64 le  |x86_64   |amd64|
| mips 64 le  |  mips 64 be |  mips 64 be |
|-|
| mips 32 be  |i386 | i386|
| mips 32 be  |x86_64   | i386|
| mips 32 be  |x86_64   | amd64   |
| mips 64 be  |i386 | i386|
| mips 64 be  |x86_64   | i386|
| mips 64 be  |x86_64   | amd64   |
| mips n32 be |386  | i386|
| mips n32 be |x86_64   | i386|
| mips n32 be |x86_64   | amd64   |

(No plan to test MIPS R6 in this patch.)

  Summary of changes from v4:

  | tcg-mips: Support 64-bit opcodes   | Fix tcg_out_bswap64() |
  | tcg-mips: Adjust qemu_ld/st for mips64 | Fix a style problem   |


Changes in v4:
  * tcg_out_qemu_ld_slow_path: always sign-extend 32-bit loads.
Provide a better solution than patch11 in v3.
Fix the blocking bug when emulating i386 kernel on mips64el.
  * Redefine LO_OFF/HI_OFF as v2.
On mips64 host, they are defined as link_error, to ensure that
all paths that lead to the use of the symbol are eliminated by
the compiler.

Changes in v3:
  * Update against master(v2.8.0-rc1)
  * Tested on Loongson as mips32r2(el) and mips64r2(el) hosts.
Loongson only implements little-endian mips32/mips64 ISA.
  * Fully work for 32-bit and 64-bit guests.
Fix two bugs:segmentation fault on mips64el with 32-bit guests,
  blocking when emulating i386 kernel on mips64el.
  * Fix some minor style problems.
  * PATCH v2 12~16 are not examined due to the lack of R6 machine. 

Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 

Jin Guojie (10):
  tcg-mips: Move bswap code to a subroutine
  tcg-mips: Add mips64 opcodes
  tcg-mips: Support 64-bit opcodes
  tcg-mips: Add bswap32u and bswap64
  tcg-mips: Adjust move functions for mips64
  tcg-mips: Adjust load/store functions for mips64
  tcg-mips: Adjust prologue for mips64
  tcg-mips: Add tcg unwind info
  tcg-mips: Adjust calling conventions for mips64
  tcg-mips: Adjust qemu_ld/st for mips64

 tcg/mips/tcg-target.h |   60 ++-
 tcg/mips/tcg-target.inc.c | 1170 +++--
 2 files changed, 977 insertions(+), 253 deletions(-)

-- 
2.1.0





[Qemu-devel] [PATCH v6 10/10] tcg-mips: Adjust qemu_ld/st for mips64

2016-12-11 Thread Jin Guojie
Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.inc.c | 203 +-
 1 file changed, 146 insertions(+), 57 deletions(-)

diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 7282a4a..b992852 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -32,8 +32,16 @@
 # define MIPS_BE  0
 #endif
 
-#define LO_OFF(MIPS_BE * 4)
-#define HI_OFF(4 - LO_OFF)
+#if TCG_TARGET_REG_BITS == 32
+# define LO_OFF  (MIPS_BE * 4)
+# define HI_OFF  (4 - LO_OFF)
+#else
+/* To assert at compile-time that these values were never used
+   for TCG_TARGET_REGS == 64 */
+/* extern */ int link_error(void);
+# define LO_OFF  link_error()
+# define HI_OFF  link_error()
+#endif
 
 #ifdef CONFIG_DEBUG_TCG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
@@ -193,7 +201,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, 
const char **pct_str)
 tcg_regset_set(ct->u.regs, 0x);
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
 #if defined(CONFIG_SOFTMMU)
-if (TARGET_LONG_BITS == 64) {
+if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
 }
 #endif
@@ -203,11 +211,11 @@ static int target_parse_constraint(TCGArgConstraint *ct, 
const char **pct_str)
 tcg_regset_set(ct->u.regs, 0x);
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
 #if defined(CONFIG_SOFTMMU)
-if (TARGET_LONG_BITS == 32) {
-tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
-} else {
+if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
+} else {
+tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
 }
 #endif
 break;
@@ -1104,6 +1112,10 @@ static void * const qemu_ld_helpers[16] = {
 [MO_BESW] = helper_be_ldsw_mmu,
 [MO_BEUL] = helper_be_ldul_mmu,
 [MO_BEQ]  = helper_be_ldq_mmu,
+#if TCG_TARGET_REG_BITS == 64
+[MO_LESL] = helper_le_ldsl_mmu,
+[MO_BESL] = helper_be_ldsl_mmu,
+#endif
 };
 
 static void * const qemu_st_helpers[16] = {
@@ -1131,6 +1143,9 @@ static int tcg_out_call_iarg_reg(TCGContext *s, int i, 
TCGReg arg)
 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
 } else {
+/* For N32 and N64, the initial offset is different.  But there
+   we also have 8 argument register so we don't run out here.  */
+tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
 tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
 }
 return i + 1;
@@ -1172,6 +1187,7 @@ static int tcg_out_call_iarg_imm(TCGContext *s, int i, 
TCGArg arg)
 
 static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
 {
+tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
 i = (i + 1) & ~1;
 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
@@ -1179,7 +1195,7 @@ static int tcg_out_call_iarg_reg2(TCGContext *s, int i, 
TCGReg al, TCGReg ah)
 }
 
 /* Perform the tlb comparison operation.  The complete host address is
-   placed in BASE.  Clobbers TMP0, TMP1, A0.  */
+   placed in BASE.  Clobbers TMP0, TMP1, TMP2, A0.  */
 static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
  TCGReg addrh, TCGMemOpIdx oi,
  tcg_insn_unit *label_ptr[2], bool is_load)
@@ -1187,6 +1203,7 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
 TCGMemOp opc = get_memop(oi);
 unsigned s_bits = opc & MO_SIZE;
 unsigned a_bits = get_alignment_bits(opc);
+target_ulong mask;
 int mem_index = get_mmuidx(oi);
 int cmp_off
 = (is_load
@@ -1194,11 +1211,11 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg 
base, TCGReg addrl,
: offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
 
-tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addrl,
+tcg_out_opc_sa(s, ALIAS_TSRL, TCG_REG_A0, addrl,
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
 (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
-tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
+tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
 
 /* Compensate for very large offsets.  */
 if (add_off >= 0x8000) {
@@ -1208,51 +1225,63 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg 
base, TCGReg addrl,
 QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
tlb_table[NB_MMU_MODES - 1][1])
  

[Qemu-devel] [PATCH v6 06/10] tcg-mips: Adjust load/store functions for mips64

2016-12-11 Thread Jin Guojie
tcg_out_ldst: using a generic ALIAS_PADD to avoid ifdefs
tcg_out_ld: generates LD or LW
tcg_out_st: generates SD or SW

Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.inc.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 18368f0..5cc8df3 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -697,7 +697,7 @@ static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, 
TCGReg data,
 if (ofs != lo) {
 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
 if (addr != TCG_REG_ZERO) {
-tcg_out_opc_reg(s, OPC_ADDU, TCG_TMP0, TCG_TMP0, addr);
+tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP0, TCG_TMP0, addr);
 }
 addr = TCG_TMP0;
 }
@@ -707,13 +707,21 @@ static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, 
TCGReg data,
 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
   TCGReg arg1, intptr_t arg2)
 {
-tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
+MIPSInsn opc = OPC_LD;
+if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
+opc = OPC_LW;
+}
+tcg_out_ldst(s, opc, arg, arg1, arg2);
 }
 
 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
   TCGReg arg1, intptr_t arg2)
 {
-tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
+MIPSInsn opc = OPC_SD;
+if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
+opc = OPC_SW;
+}
+tcg_out_ldst(s, opc, arg, arg1, arg2);
 }
 
 static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
-- 
2.1.0





[Qemu-devel] [PATCH v6 07/10] tcg-mips: Adjust prologue for mips64

2016-12-11 Thread Jin Guojie
Take stack frame parameters out from the function body.

Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.inc.c | 54 ++-
 1 file changed, 25 insertions(+), 29 deletions(-)

diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 5cc8df3..9e24662 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -734,16 +734,6 @@ static inline bool tcg_out_sti(TCGContext *s, TCGType 
type, TCGArg val,
 return false;
 }
 
-static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
-{
-if (val == (int16_t)val) {
-tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
-} else {
-tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, val);
-tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_TMP0);
-}
-}
-
 static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
 TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
 bool cbh, bool is_sub)
@@ -2270,42 +2260,48 @@ static tcg_insn_unit *align_code_ptr(TCGContext *s)
 return s->code_ptr;
 }
 
+/* Stack frame parameters.  */
+#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
+#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
+#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
+
+#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
+ + TCG_TARGET_STACK_ALIGN - 1) \
+& -TCG_TARGET_STACK_ALIGN)
+#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
+
+/* We're expecting to be able to use an immediate for frame allocation.  */
+QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff);
+
 /* Generate global QEMU prologue and epilogue code */
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
-int i, frame_size;
+int i;
 
-/* reserve some stack space, also for TCG temps. */
-frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
- + TCG_STATIC_CALL_ARGS_SIZE
- + CPU_TEMP_BUF_NLONGS * sizeof(long);
-frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
- ~(TCG_TARGET_STACK_ALIGN - 1);
-tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
-  + TCG_STATIC_CALL_ARGS_SIZE,
-  CPU_TEMP_BUF_NLONGS * sizeof(long));
+tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
 
 /* TB prologue */
-tcg_out_addi(s, TCG_REG_SP, -frame_size);
-for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
-tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
-   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
+tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
+for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
 }
 
 /* Call generated code */
 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
+/* delay slot */
 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
-tb_ret_addr = s->code_ptr;
 
 /* TB epilogue */
-for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
-tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
-   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
+tb_ret_addr = s->code_ptr;
+for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
 }
 
 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
 /* delay slot */
-tcg_out_addi(s, TCG_REG_SP, frame_size);
+tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
 
 if (use_mips32r2_instructions) {
 return;
-- 
2.1.0





[Qemu-devel] [PATCH v6 09/10] tcg-mips: Adjust calling conventions for mips64

2016-12-11 Thread Jin Guojie
Tested-by: Aurelien Jarno 
Tested-by: James Hogan 
Tested-by: YunQiang Su 
Signed-off-by: Richard Henderson 
Signed-off-by: Jin Guojie 
---
 tcg/mips/tcg-target.h | 19 +++
 tcg/mips/tcg-target.inc.c | 21 +++--
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 4b7d3ae..d352c97 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -27,7 +27,14 @@
 #ifndef MIPS_TCG_TARGET_H
 #define MIPS_TCG_TARGET_H
 
-#define TCG_TARGET_REG_BITS 32
+#if _MIPS_SIM == _ABIO32
+# define TCG_TARGET_REG_BITS 32
+#elif _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
+# define TCG_TARGET_REG_BITS 64
+#else
+# error "Unknown ABI"
+#endif
+
 #define TCG_TARGET_INSN_UNIT_SIZE 4
 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 16
 #define TCG_TARGET_NB_REGS 32
@@ -71,9 +78,13 @@ typedef enum {
 } TCGReg;
 
 /* used for function call generation */
-#define TCG_TARGET_STACK_ALIGN 8
-#define TCG_TARGET_CALL_STACK_OFFSET 16
-#define TCG_TARGET_CALL_ALIGN_ARGS 1
+#define TCG_TARGET_STACK_ALIGN16
+#if _MIPS_SIM == _ABIO32
+# define TCG_TARGET_CALL_STACK_OFFSET 16
+#else
+# define TCG_TARGET_CALL_STACK_OFFSET 0
+#endif
+#define TCG_TARGET_CALL_ALIGN_ARGS1
 
 /* MOVN/MOVZ instructions detection */
 #if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index b7e2586..7282a4a 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -91,10 +91,6 @@ static const int tcg_target_reg_alloc_order[] = {
 TCG_REG_S8,
 
 /* Call clobbered registers.  */
-TCG_REG_T0,
-TCG_REG_T1,
-TCG_REG_T2,
-TCG_REG_T3,
 TCG_REG_T4,
 TCG_REG_T5,
 TCG_REG_T6,
@@ -105,17 +101,27 @@ static const int tcg_target_reg_alloc_order[] = {
 TCG_REG_V0,
 
 /* Argument registers, opposite order of allocation.  */
+TCG_REG_T3,
+TCG_REG_T2,
+TCG_REG_T1,
+TCG_REG_T0,
 TCG_REG_A3,
 TCG_REG_A2,
 TCG_REG_A1,
 TCG_REG_A0,
 };
 
-static const TCGReg tcg_target_call_iarg_regs[4] = {
+static const TCGReg tcg_target_call_iarg_regs[] = {
 TCG_REG_A0,
 TCG_REG_A1,
 TCG_REG_A2,
-TCG_REG_A3
+TCG_REG_A3,
+#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
+TCG_REG_T0,
+TCG_REG_T1,
+TCG_REG_T2,
+TCG_REG_T3,
+#endif
 };
 
 static const TCGReg tcg_target_call_oarg_regs[2] = {
@@ -2427,6 +2433,9 @@ static void tcg_target_init(TCGContext *s)
 {
 tcg_target_detect_isa();
 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0x);
+if (TCG_TARGET_REG_BITS == 64) {
+tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I64], 0x);
+}
 tcg_regset_set(tcg_target_call_clobber_regs,
(1 << TCG_REG_V0) |
(1 << TCG_REG_V1) |
-- 
2.1.0





Re: [Qemu-devel] [PATCH 4/4] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered

2016-12-11 Thread Christoffer Dall
On Fri, Dec 09, 2016 at 04:30:20PM +, Peter Maydell wrote:
> The architectural timers in ARM CPUs all have level triggered interrupts
> (unless you're using KVM on a host kernel before 4.4, which misimplemented
> them as edge-triggered).
> 
> We were incorrectly describing them in the device tree as edge triggered.
> This can cause problems for guest kernels in 4.8 before rc6:
>  * pre-4.8 kernels ignore the values in the DT
>  * 4.8 before rc6 write the DT values to the GIC config registers
>  * newer than rc6 ignore the DT and insist that the timer interrupts
>are level triggered regardless
> 
> Fix the DT so we're describing reality. For backwards-compatibility
> purposes, only do this for the virt-2.9 machine onward.
> 
> Signed-off-by: Peter Maydell 
> ---
>  hw/arm/virt.c | 34 ++
>  1 file changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 54498ea..2ca9527 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -71,6 +71,7 @@ typedef struct {
>  bool disallow_affinity_adjustment;
>  bool no_its;
>  bool no_pmu;
> +bool claim_edge_triggered_timers;
>  } VirtMachineClass;
>  
>  typedef struct {
> @@ -309,12 +310,31 @@ static void fdt_add_psci_node(const VirtMachineState 
> *vms)
>  
>  static void fdt_add_timer_nodes(const VirtMachineState *vms, int gictype)
>  {
> -/* Note that on A15 h/w these interrupts are level-triggered,
> - * but for the GIC implementation provided by both QEMU and KVM
> - * they are edge-triggered.
> +/* On real hardware these interrupts are level-triggered.
> + * On KVM they were edge-triggered before host kernel version 4.4,
> + * and level-triggered afterwards.
> + * On emulated QEMU they are level-triggered.
> + *
> + * Getting the DTB info about them wrong is awkward for some
> + * guest kernels:
> + *  pre-4.8 ignore the DT and leave the interrupt configured
> + *   with whatever the GIC reset value (or the bootloader) left it at
> + *  4.8 before rc6 honour the incorrect data by programming it back
> + *   into the GIC, causing problems
> + *  4.8rc6 and later ignore the DT and always write "level triggered"
> + *   into the GIC
> + *
> + * For backwards-compatibility, virt-2.8 and earlier will continue
> + * to say these are edge-triggered, but later machines will report
> + * the correct information.
>   */

Is this really necessary?

I don't think the KVM GIC implementation ever listened to the guest in
terms of how to configure PPIs, but instead ignores writes to the config
registers for these interrupts (which I think the GIC architecture
allows).

So this would only be a matter of how the guest kernel between v4.8-rc1
and v4.8-rc6 expects the behavior to be.  Does the arch timer driver
really do something different in how it deals with interrupts based on
this DT value?

Of course, I suppose we could also be running other guests (UEFI?) but
again, if the KVM GIC doesn't care about how the guest tries to program
it, can it make a difference?

>  ARMCPU *armcpu;
> -uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
> +VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
> +uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
> +
> +if (vmc->claim_edge_triggered_timers) {
> +irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
> +}
>  
>  if (gictype == 2) {
>  irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
> @@ -1556,8 +1576,14 @@ static void virt_2_8_instance_init(Object *obj)
>  
>  static void virt_machine_2_8_options(MachineClass *mc)
>  {
> +VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
> +
>  virt_machine_2_9_options(mc);
>  SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_8);
> +/* For 2.8 and earlier we falsely claimed in the DT that
> + * our timers were edge-triggered, not level-triggered.
> + */
> +vmc->claim_edge_triggered_timers = true;
>  }
>  DEFINE_VIRT_MACHINE(2, 8)
>  
I don't understand this virt machine class version stuff.  In which case
is the claim_edge_triggered_timers set to true?  (ok, appears to be when
a 2.8 machine is created, but does that happen automatically or does the
user specifically have to ask for it?)

Thanks,
-Christoffer



[Qemu-devel] aarch64-linux-user compilation error

2016-12-11 Thread Pranith Kumar
Hi,

I am getting a strange compilation error lately for aarch64-linux-user. I
think it is somehow related to TYPE_PTRVOID handling but my investigation has
not led to anything concrete. I think this is a compiler error since the build
passes on an other system with gcc-6.

Info: ubuntu 16.04 x86_64 system

$ gcc --version
gcc (Ubuntu 5.4.1-2ubuntu1~16.04) 5.4.1 20160904

Error:
/home/pranith/devops/code/qemu/linux-user/ioctls.h:224:9: error: 
‘SNDCTL_DSP_MAPINBUF’ undeclared here (not in a function)
   IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc)))
 ^
/home/pranith/devops/code/qemu/linux-user/syscall.c:5453:23: note: in 
definition of macro ‘IOCTL’
 { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
   ^
/home/pranith/devops/code/qemu/linux-user/ioctls.h:225:9: error: 
‘SNDCTL_DSP_MAPOUTBUF’ undeclared here (not in a function)
   IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc)))
 ^
/home/pranith/devops/code/qemu/linux-user/syscall.c:5453:23: note: in 
definition of macro ‘IOCTL’
 { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
   ^
/home/pranith/devops/code/qemu/linux-user/ioctls.h:280:9: error: 
‘SOUND_MIXER_ACCESS’ undeclared here (not in a function)
   IOCTL(SOUND_MIXER_ACCESS, 0, TYPE_PTRVOID)
 ^
/home/pranith/devops/code/qemu/linux-user/syscall.c:5453:23: note: in 
definition of macro ‘IOCTL’
 { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
   ^
/home/pranith/devops/code/qemu/rules.mak:60: recipe for target 
'linux-user/syscall.o' failed

-- 
Pranith



Re: [Qemu-devel] aarch64-linux-user compilation error

2016-12-11 Thread Pranith Kumar
On Sun, Dec 11, 2016 at 2:09 PM, Pranith Kumar  wrote:
> Hi,
>
> I am getting a strange compilation error lately for aarch64-linux-user. I
> think it is somehow related to TYPE_PTRVOID handling but my investigation has
> not led to anything concrete. I think this is a compiler error since the build
> passes on an other system with gcc-6.
>
> Info: ubuntu 16.04 x86_64 system
>
> $ gcc --version
> gcc (Ubuntu 5.4.1-2ubuntu1~16.04) 5.4.1 20160904
>

The issue occurs even with a newer gcc.

$ gcc --version
gcc (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901

-- 
Pranith



Re: [Qemu-devel] [PATCH 4/4] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered

2016-12-11 Thread Peter Maydell
On 11 December 2016 at 16:35, Christoffer Dall
 wrote:
> On Fri, Dec 09, 2016 at 04:30:20PM +, Peter Maydell wrote:
>> + * For backwards-compatibility, virt-2.8 and earlier will continue
>> + * to say these are edge-triggered, but later machines will report
>> + * the correct information.
>>   */
>
> Is this really necessary?

It's being conservative -- from the guest's point of view
(any guest, not necessarily just Linux) "virt-2.8" should behave
like the "virt" machine in the 2.8 QEMU release, including bugs,
not providing newer devices, and so on.

Andrew would be the expert on whether this is being unnecessarily
conservative in this specific case.

>>  static void virt_machine_2_8_options(MachineClass *mc)
>>  {
>> +VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
>> +
>>  virt_machine_2_9_options(mc);
>>  SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_8);
>> +/* For 2.8 and earlier we falsely claimed in the DT that
>> + * our timers were edge-triggered, not level-triggered.
>> + */
>> +vmc->claim_edge_triggered_timers = true;
>>  }
>>  DEFINE_VIRT_MACHINE(2, 8)
>>
> I don't understand this virt machine class version stuff.  In which case
> is the claim_edge_triggered_timers set to true?  (ok, appears to be when
> a 2.8 machine is created, but does that happen automatically or does the
> user specifically have to ask for it?)

If you say "-M virt-2.8" (or -2.7 or earlier, etc), it's set
to true. If you say "-M virt" or "-M virt-2.9" (or "-M virt-2.10"
or whatever we call the next release) it stays at the default
false.

thanks
-- PMM



Re: [Qemu-devel] aarch64-linux-user compilation error

2016-12-11 Thread Peter Maydell
On 11 December 2016 at 19:09, Pranith Kumar  wrote:
> I am getting a strange compilation error lately for aarch64-linux-user. I
> think it is somehow related to TYPE_PTRVOID handling but my investigation has
> not led to anything concrete. I think this is a compiler error since the build
> passes on an other system with gcc-6.

> Error:
> /home/pranith/devops/code/qemu/linux-user/ioctls.h:224:9: error: 
> ‘SNDCTL_DSP_MAPINBUF’ undeclared here (not in a function)
>IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc)))
>  ^

SNDCTL_DSP_MAPINBUF is supposed to be defined by your system
headers (/usr/include/linux/soundcard.h or equivalent).
Similarly for SNDCTL_DSP_MAPOUTBUF and SOUND_MIXER_ACCESS.

Looking at QEMU's git history we've used these symbols
for years. I would check whether your system headers
are actually providing these symbols (and that the
compiler is really putting the right headers on the
include path).

thanks
-- PMM



[Qemu-devel] [Bug 1648726] Re: [usb-host] Passthrough of UAS devices fails with Windows (10) guests

2016-12-11 Thread Jack Coulter
** Summary changed:

- Passthrough of UAS devices fails with Windows (10) guests
+ [usb-host] Passthrough of UAS devices fails with Windows (10) guests

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

Title:
  [usb-host] Passthrough of UAS devices fails with Windows (10) guests

Status in QEMU:
  New

Bug description:
  Split off from https://bugs.launchpad.net/qemu/+bug/1579306 as this is
  a distinct issue.

  Physical USB storage devices that support the UAS protocol do not work
  correctly when passed through to Windows guests (I've only tested this
  with Windows 10 x64, build 1607).

  Passing through such a device results in the older BOT/MSC protocol
  being used:

  

  Using the same domain configuration with a Linux guest (tested with
  SystemRescueCD 4.8.0) works correctly:

  /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
  |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M
  /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M

  In both cases, the VM was launched via libvirt, which generated the
  following command line:

  /usr/bin/qemu-system-x86_64 -name guest=Win10-Edge-IE11,debug-
  threads=on -S -object
  secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-13-Win10
  -Edge-IE11/master-key.aes -machine
  pc-q35-2.7,accel=kvm,usb=off,vmport=off,dump-guest-core=off -cpu
  host,hv_time,hv_relaxed,hv_vapic,hv_spinlocks=0x1fff -m 4096 -realtime
  mlock=off -smp 8,sockets=1,cores=4,threads=2 -uuid 47c39707-088c-4edc-
  8b6a-a7856e09f43d -no-user-config -nodefaults -chardev
  socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-13-Win10-Edge-
  IE11/monitor.sock,server,nowait -mon
  chardev=charmonitor,id=monitor,mode=control -rtc
  base=localtime,driftfix=slew -global kvm-pit.lost_tick_policy=discard
  -no-hpet -no-shutdown -global ICH9-LPC.disable_s3=1 -global
  ICH9-LPC.disable_s4=1 -boot strict=on -device
  i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e -device pci-
  bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 -device nec-usb-
  xhci,id=usb,bus=pci.2,addr=0x6 -device virtio-scsi-
  pci,id=scsi0,bus=pci.2,addr=0x3 -device virtio-serial-pci,id=virtio-
  serial0,bus=pci.2,addr=0x4 -drive file=/home/jack/IMG/Win10-Edge-
  IE11.qcow2,format=qcow2,if=none,id=drive-scsi0-0-0-0,discard=unmap
  -device scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-
  scsi0-0-0-0,id=scsi0-0-0-0,bootindex=1 -drive if=none,id=drive-
  scsi0-0-0-1,readonly=on -device scsi-cd,bus=scsi0.0,channel=0,scsi-
  id=0,lun=1,drive=drive-scsi0-0-0-1,id=scsi0-0-0-1 -netdev
  tap,fd=22,id=hostnet0,vhost=on,vhostfd=24 -device virtio-net-
  pci,netdev=hostnet0,id=net0,mac=52:54:00:27:94:5d,bus=pci.2,addr=0x1
  -chardev pty,id=charserial0 -device isa-
  serial,chardev=charserial0,id=serial0 -chardev
  spicevmc,id=charchannel0,name=vdagent -device virtserialport,bus
  =virtio-
  serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0
  -device usb-tablet,id=input0,bus=usb.0,port=2 -spice
  port=5900,addr=127.0.0.1,disable-ticketing,image-compression=off
  ,seamless-migration=on -device qxl-
  
vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=16,max_outputs=1,bus=pcie.0,addr=0x1
  -device intel-hda,id=sound0,bus=pci.2,addr=0x2 -device hda-
  duplex,id=sound0-codec0,bus=sound0.0,cad=0 -chardev
  spicevmc,id=charredir0,name=usbredir -device usb-
  redir,chardev=charredir0,id=redir0,bus=usb.0,port=3 -chardev
  spicevmc,id=charredir1,name=usbredir -device usb-
  redir,chardev=charredir1,id=redir1,bus=usb.0,port=4 -device usb-
  host,hostbus=4,hostaddr=4,id=hostdev0,bus=usb.0,port=1 -device virtio-
  balloon-pci,id=balloon0,bus=pci.2,addr=0x5 -msg timestamp=on

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



Re: [Qemu-devel] [PATCH 01/20] Makefile: Allow CPU targets to reside in target/ folder, too

2016-12-11 Thread David Gibson
On Sat, Dec 10, 2016 at 11:59:09AM +0100, Laurent Vivier wrote:
> Le 09/12/2016 à 17:51, Thomas Huth a écrit :
> > On 09.12.2016 13:24, Laurent Vivier wrote:
> >> Le 09/12/2016 à 13:17, Thomas Huth a écrit :
> >>> To be able to compile the CPU targets from within a subfolder
> >>> of the target/ folder, we've got to adapt the Makefile.target
> >>> a little bit first. After this change, target CPUs can either
> >>> reside in a target/xxx folder or continue to use the target-xxx
> >>> scheme. The latter will be disabled once all targets have been
> >>> moved.
> >>>
> >>> Signed-off-by: Thomas Huth 
> >>> ---
> >>>  Makefile.target | 10 --
> >>>  1 file changed, 8 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/Makefile.target b/Makefile.target
> >>> index 7a5080e..90b25ae 100644
> >>> --- a/Makefile.target
> >>> +++ b/Makefile.target
> >>> @@ -7,11 +7,17 @@ include config-target.mak
> >>>  include config-devices.mak
> >>>  include $(SRC_PATH)/rules.mak
> >>>  
> >>> +ifneq ($(wildcard $(SRC_PATH)/target/$(TARGET_BASE_ARCH)),)
> >>> +TARGET_FOLDER=target/$(TARGET_BASE_ARCH)
> >>> +else
> >>> +TARGET_FOLDER=target-$(TARGET_BASE_ARCH)
> >>> +endif
> >>
> >> Perhaps you should consider to use ':=' instead of '='.
> > 
> > Most of the other variables in that file seem to be set with '=' instead
> > of ':=', so using '=' sounds more consistent to me ... is there a real
> > benefit of using ':=' here?
> 
> With ':=' your variable is expanded once, with '=' it is expanded
> whenever it is used. I think this is not needed in your case.
> 
> https://www.gnu.org/software/make/manual/html_node/Flavors.html#Flavors

I tend to thing '=' is the safer default option unless you're really
hitting performance problems that ':=' can alleviate.  Not
re-expanding can lead to confusing bugs later if the definition is
changed so that re-expansion matters in future.

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH v2 5/6] target-ppc: implement xxextractuw instruction

2016-12-11 Thread David Gibson
On Fri, Dec 09, 2016 at 05:47:24PM +0530, Nikunj A Dadhania wrote:
> xxextractuw: VSX Vector Extract Unsigned Word
> 
> Signed-off-by: Nikunj A Dadhania 
> ---
>  target-ppc/helper.h |  1 +
>  target-ppc/int_helper.c | 21 +
>  target-ppc/translate/vsx-impl.inc.c | 27 +++
>  target-ppc/translate/vsx-ops.inc.c  |  5 +
>  4 files changed, 54 insertions(+)
> 
> diff --git a/target-ppc/helper.h b/target-ppc/helper.h
> index 4707db4..8b30420 100644
> --- a/target-ppc/helper.h
> +++ b/target-ppc/helper.h
> @@ -540,6 +540,7 @@ DEF_HELPER_2(xvrspip, void, env, i32)
>  DEF_HELPER_2(xvrspiz, void, env, i32)
>  DEF_HELPER_2(xxperm, void, env, i32)
>  DEF_HELPER_2(xxpermr, void, env, i32)
> +DEF_HELPER_4(xxextractuw, void, env, tl, tl, i32)
>  
>  DEF_HELPER_2(efscfsi, i32, env, i32)
>  DEF_HELPER_2(efscfui, i32, env, i32)
> diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
> index 7989b1f..e3f66ac 100644
> --- a/target-ppc/int_helper.c
> +++ b/target-ppc/int_helper.c
> @@ -2033,6 +2033,27 @@ VEXTRACT(uw, u32)
>  VEXTRACT(d, u64)
>  #undef VEXTRACT
>  
> +void helper_xxextractuw(CPUPPCState *env, target_ulong xtn,
> +target_ulong xbn, uint32_t index)
> +{
> +ppc_vsr_t xt, xb;
> +size_t es = sizeof(uint32_t);
> +uint32_t ext_index;
> +
> +getVSR(xbn, &xb, env);
> +memset(&xt, 0, sizeof(xt));
> +
> +#if defined(HOST_WORDS_BIGENDIAN)
> +ext_index = index;
> +memcpy(&xt.u8[8 - es], &xb.u8[ext_index], es);
> +#else
> +ext_index = (16 - index) - es;
> +memcpy(&xt.u8[8], &xb.u8[ext_index], es);

Hm.  So, IIUC, ext_index is the byte element - in IBM numbering - to
start copying from.  But I thought that when we have an LE host, the
IBM byte element ordering is reversed from the actual order in host
memory, so we'd need &xb.u8[16 - ext_index - es]

> +#endif
> +
> +putVSR(xtn, &xt, env);
> +}
> +
>  #define VEXT_SIGNED(name, element, mask, cast, recast)  \
>  void helper_##name(ppc_avr_t *r, ppc_avr_t *b)  \
>  {   \
> diff --git a/target-ppc/translate/vsx-impl.inc.c 
> b/target-ppc/translate/vsx-impl.inc.c
> index 2a17c35..1c40a35 100644
> --- a/target-ppc/translate/vsx-impl.inc.c
> +++ b/target-ppc/translate/vsx-impl.inc.c
> @@ -1180,6 +1180,33 @@ static void gen_xxsldwi(DisasContext *ctx)
>  tcg_temp_free_i64(xtl);
>  }
>  
> +#define VSX_EXTRACT(name)   \
> +static void gen_##name(DisasContext *ctx)   \
> +{   \
> +TCGv xt, xb;\
> +TCGv_i32 t0 = tcg_temp_new_i32();   \
> +uint8_t uimm = UIMM4(ctx->opcode);  \
> +\
> +if (unlikely(!ctx->vsx_enabled)) {  \
> +gen_exception(ctx, POWERPC_EXCP_VSXU);  \
> +return; \
> +}   \
> +if (uimm > 12) {\

Throughout the helper you use es == sizeof(uint32_t), but here you
hardcode the assumption of 4 bytes, seems a bit inconsistent.

> +tcg_gen_movi_i64(cpu_vsrh(xT(ctx->opcode)), 0); \
> +tcg_gen_movi_i64(cpu_vsrl(xT(ctx->opcode)), 0); \
> +return; \

So, I know the architecture says it is undefined.  But since you're
testing for the bogus case anyway, why not turn this into an
exception.  That seems like it would be more helpful for debugging the
guest than just setting the result to zero.  Or is this done to match
actual hardware behaviour?

> +}   \
> +xt = tcg_const_tl(xT(ctx->opcode)); \
> +xb = tcg_const_tl(xB(ctx->opcode)); \
> +tcg_gen_movi_i32(t0, uimm); \
> +gen_helper_##name(cpu_env, xt, xb, t0); \
> +tcg_temp_free(xb);  \
> +tcg_temp_free(xt);  \
> +tcg_temp_free_i32(t0);  \
> +}
> +
> +VSX_EXTRACT(xxextractuw)
> +
>  #undef GEN_XX2FORM
>  #undef GEN_XX3FORM
>  #undef GEN_XX2IFORM
> diff --git a/target-ppc/translate/vsx-ops.inc.c 
> b/target-ppc/translate/vsx-ops.inc.c
> index 46b95e3..473d925 100644
> --- a/target-ppc/translate/vsx-ops.inc.c
> +++ b/target-ppc/translate/vsx-ops.inc.c
> @@ -49,6 +49,10 @@ GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, 
> PPC_NONE, fl2)
>  GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
> 

Re: [Qemu-devel] [PATCH v2 ppc-for-2.9 0/6] POWER9 TCG enablements - part9

2016-12-11 Thread David Gibson
On Fri, Dec 09, 2016 at 05:47:19PM +0530, Nikunj A Dadhania wrote:
> This series contains 6 new instructions for POWER9 ISA3.0
>  VSX Vector Insert/Extract Word
>  VSX Load/Store with length
> 
> Although, lxvl/lxvll and stxvl/stxvll can be combined as single patch,
> have left it for detailed commit log for instruction explanation.

I've applied patches 1-4 to ppc-for-2.9.  5 & 6 I still have some
questions about.
> 
> Changelog:
> v1:
> * Combine helpers of lxvl and lxvll
> * Combine helpers of stxvl and stxvll
> * Rework xxextractuw and xxinsertw to simplify helper
> 
> v0:
> * Fixed lxvl/lxvll and stxvl/stxvll as suggested by Richard
> * Dropped mask_u128, which is not needed anymore
> * Prevent UIMM > 12 in xxextractuw
> * Drop xori from xsnegqp
> * Rewrite xxperm/xxpermr without double copy
> 
> Nikunj A Dadhania (6):
>   target-ppc: implement lxvl instruction
>   target-ppc: implement lxvll instruction
>   target-ppc: implement stxvl instruction
>   target-ppc: implement stxvll instructions
>   target-ppc: implement xxextractuw instruction
>   target-ppc: implement xxinsertw instruction
> 
>  target-ppc/helper.h |  8 +
>  target-ppc/int_helper.c | 42 +++
>  target-ppc/mem_helper.c | 66 
> +
>  target-ppc/translate/vsx-impl.inc.c | 60 +
>  target-ppc/translate/vsx-ops.inc.c  | 14 
>  5 files changed, 190 insertions(+)
> 

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] [for-2.9 2/5] pseries: Stubs for HPT resizing

2016-12-11 Thread David Gibson
On Fri, Dec 09, 2016 at 11:08:02AM -0600, Michael Roth wrote:
> Quoting David Gibson (2016-12-08 20:23:11)
> > This introduces stub implementations of the H_RESIZE_HPT_PREPARE and
> > H_RESIZE_HPT_COMMIT hypercalls which we hope to add in a PAPR
> > extension to allow run time resizing of a guest's hash page table.  It
> > also adds a new machine property for controlling whether this new
> > facility is available, and logic to check that against availability
> > with KVM (only supported with KVM PR for now).
> > 
> > Finally, it adds a new string to the hypertas property in the device
> > tree, advertising to the guest the availability of the HPT resizing
> > hypercalls.  This is a tentative suggested value, and would need to be
> > standardized by PAPR before being merged.
> > 
> > Signed-off-by: David Gibson 
> > ---
> >  hw/ppc/spapr.c | 66 
> > ++
> >  hw/ppc/spapr_hcall.c   | 36 +++
> >  hw/ppc/trace-events|  2 ++
> >  include/hw/ppc/spapr.h | 11 +
> >  target-ppc/kvm.c   | 26 
> >  target-ppc/kvm_ppc.h   |  5 
> >  6 files changed, 146 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index 0f25e83..ecb0822 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -760,6 +760,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, 
> > void *fdt)
> >  if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> >  add_str(hypertas, "hcall-multi-tce");
> >  }
> > +
> > +if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
> > +add_str(hypertas, "hcall-hpt-resize");
> > +}
> > +
> >  _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions",
> >   hypertas->str, hypertas->len));
> >  g_string_free(hypertas, TRUE);
> > @@ -1839,11 +1844,31 @@ static void ppc_spapr_init(MachineState *machine)
> >  long load_limit, fw_size;
> >  char *filename;
> >  int smt = kvmppc_smt_threads();
> > +Error *resize_hpt_err = NULL;
> > 
> >  msi_nonbroken = true;
> > 
> >  QLIST_INIT(&spapr->phbs);
> > 
> > +/* Check HPT resizing availability */
> > +kvmppc_check_papr_resize_hpt(&resize_hpt_err);
> > +if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) {
> > +if (resize_hpt_err) {
> > +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
> > +error_free(resize_hpt_err);
> > +resize_hpt_err = NULL;
> > +} else {
> > +spapr->resize_hpt = smc->resize_hpt_default;
> > +}
> > +}
> > +
> > +assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT);
> > +
> > +if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && 
> > resize_hpt_err) {
> > +error_report_err(resize_hpt_err);
> > +exit(1);
> > +}
> 
> I'm also a bit confused by this. Aren't semantics that HPT_ENABLED will allow
> a fallback to non-resizable HPTs if the feature isn't available (whereas
> HPT_REQUIRED won't)? I don't understand how such a fallback can ever be 
> reached
> with this check in place.

We fall back if the _guest_ doesn't support HPT resizing.  This error
path is if the _host_ can't support HPT resizing.  Some extra
information about this in the reply I'll shortly send to Thomas.

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] aarch64-linux-user compilation error

2016-12-11 Thread Pranith Kumar
On Sun, Dec 11, 2016 at 5:59 PM, Peter Maydell  wrote:
>
>> Error:
>> /home/pranith/devops/code/qemu/linux-user/ioctls.h:224:9: error: 
>> ‘SNDCTL_DSP_MAPINBUF’ undeclared here (not in a function)
>>IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc)))
>>  ^
>
> SNDCTL_DSP_MAPINBUF is supposed to be defined by your system
> headers (/usr/include/linux/soundcard.h or equivalent).
> Similarly for SNDCTL_DSP_MAPOUTBUF and SOUND_MIXER_ACCESS.
>
> Looking at QEMU's git history we've used these symbols
> for years. I would check whether your system headers
> are actually providing these symbols (and that the
> compiler is really putting the right headers on the
> include path).

So soundcard.h header is provided by two packages:

$ apt-file search /usr/include/linux/soundcard.h
linux-libc-dev: /usr/include/linux/soundcard.h
oss4-dev: /usr/include/linux/soundcard.h

I had oss4-dev installed. After removing that and reinstalling
linux-libc-dev, it compiles fine. Not sure why this file differs. May
be a packaging issue.

Thanks for the help!
-- 
Pranith



Re: [Qemu-devel] [PATCH for-2.9 1/2] intel_iommu: check validity for GAW bits in CE

2016-12-11 Thread Peter Xu
On Thu, Dec 08, 2016 at 10:21:35AM +0800, Jason Wang wrote:
> 
> 
> On 2016年12月08日 10:16, Peter Xu wrote:
> >On Thu, Dec 08, 2016 at 10:02:15AM +0800, Jason Wang wrote:
> >>
> >>On 2016年12月07日 13:52, Peter Xu wrote:
> >>>Currently vt-d Context Entry (CE) only allows 39/48 bits address width.
> >>>If guest software configured more than that, we complain and force
> >>>shrink to the maximum supported, which is 48bits.
> >>>
> >>>Signed-off-by: Peter Xu 
> >>>---
> >>>  hw/i386/intel_iommu.c  | 12 +++-
> >>>  hw/i386/intel_iommu_internal.h |  2 ++
> >>>  2 files changed, 13 insertions(+), 1 deletion(-)
> >>>
> >>>diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> >>>index 5f3e351..98d45ef 100644
> >>>--- a/hw/i386/intel_iommu.c
> >>>+++ b/hw/i386/intel_iommu.c
> >>>@@ -601,7 +601,17 @@ static inline uint32_t 
> >>>vtd_get_level_from_context_entry(VTDContextEntry *ce)
> >>>  static inline uint32_t vtd_get_agaw_from_context_entry(VTDContextEntry 
> >>> *ce)
> >>>  {
> >>>-return 30 + (ce->hi & VTD_CONTEXT_ENTRY_AW) * 9;
> >>>+uint8_t aw = (ce->hi & VTD_CONTEXT_ENTRY_AW);
> >>>+/*
> >>>+ * According to vt-d spec 10.4.2 bits 12:8, SAGAW only allows
> >>>+ * 39/48 bits.
> >>>+ */
> >>>+if (aw > VTD_CE_AW_48BIT) {
> >>>+error_report("Context entry address width not supported (aw=%d), "
> >>>+ "Shrinking to maximum.", aw);
> >>>+aw = VTD_CE_AW_48BIT;
> >>>+}
> >>Is this behavior specified by spec?
> >That's how I understand spec 10.4.2 bits 12:8 (as mentioned in above
> >comment). Only 39/48 bits AGAW are allowed, and others are reserved.
> >
> >When writting up this patch, I thought illegal value for this aw bits
> >(from guest software) might cause trouble, but I was wrong, since we
> >have a "MIN(ce_agaw, VTD_MGAW)" check later on. So that won't be a
> >problem, and this patch is not that necessary now.
> >
> >Thanks,
> >
> >-- peterx
> 
> Yes, and it can even report DMAR fault to guest which is better.

Yes. Will respin, thanks. :-)

-- peterx



Re: [Qemu-devel] [PATCH for-2.9 2/2] intel_iommu: extend supported guest aw to 48 bits

2016-12-11 Thread Peter Xu
On Sun, Dec 11, 2016 at 05:13:45AM +0200, Michael S. Tsirkin wrote:
> On Wed, Dec 07, 2016 at 01:52:45PM +0800, Peter Xu wrote:
> > Previously vt-d codes only supports 39 bits iova address width. It won't
> > be hard to extend it to 48 bits.
> > 
> > After enabling this, we should be able to map larger iova addresses.
> > 
> > To check whether 48 bits aw is enabled, we can grep in the guest dmesg
> > with line: "dmar: Host address width 48" (previously it was 39).
> > 
> > Signed-off-by: Peter Xu 
> 
> I suspect we can't do this for old machine types.
> Need to behave in compatible ways.

Sure. I can do that.

Btw, is vt-d iommu still in experimental stage? I am just thinking
whether it'll be overkill we add lots of tunables before we have one
stable and mature vt-d emulation.

> Also, is 48 always enough? 5 level with 57 bits
> is just around the corner.

Please refer to the discussion with Jason - looks like vt-d spec
currently supports only 39/48 bits address width? Please correct if I
made a mistake.

> And is it always supported? for things like vfio
> to work, don't we need to check what does host support?

Hmm, yes, we should do that. But until now, we still don't have a
complete vfio support. IMHO we can postpone this issue until vfio is
fully supported.

Thanks,

-- peterx



Re: [Qemu-devel] An issue for migration determining the cpu throttle value according to workload

2016-12-11 Thread Chao Fan
ping...

Thanks,
Chao Fan

On Tue, Dec 06, 2016 at 04:52:11PM +0800, Chao Fan wrote:
>Hi all,
>
>Here is an issue in auto-converge feature of migration.
>
>When migrating a guest which consumes too much CPU & memory, dirty
>pages amount will increase significantly, so does the migration
>time, migration can not even complete, at worst.
>
>I did some simple tests on this feature. Set the two parameters
>the same as 10,20,30,40,50,60,70,80,99 and run the same task in the
>same guest. The result roughly is, with the increment of the
>two parameters, the total_time and the dirty_sync_count will decrease.
>Result shows larger the value of the two parameters is, faster the
>migration is, but much more slowly the guest runs.
>
>So I think there should be a appropriate throttle value according to
>the workload of guest. But users do not know how to determine the
>appropriate value.
>
>So I want to do a job that qemu can set the throttle value according
>to the workload of guest. I think qemu could calculate the instant
>dirty pages rate, and then determine a appropriate throttle value.
>The instant dirty pages rate means in a short fixed time, how
>many dirty pages born. But I have two questions:
>1. Where to add this feature. I have two options:
>   a. Now qemu detects the rest migration time and decides whether
>  to execute the CPU throttle. It can be changed to that qemu
>  executes the CPU throttle when instant dirty pages rate increases
>  to a certain threshold and sets the throttle value according to
>  the instant dirty pages rate. 
>   b. Using the current way as it is, when the rest migration time
>  is too long and begin to execute the CPU throttle, assign
>  appropriate throttle value according to the workload. Codes
>  will be changed fewer in this method.
>2. How to determine the CPU throttle value according to the dirty pages.
>   My preliminary idea is, the CPU throttle should be related to
>   the instant dirty pages rate and the total memory.
>   But I am not sure how to do the map from instant dirty pages rate
>   and total memory to CPU throttle value is best.
>
>Any comments will be welcome, and I want to know whether more people
>think this feature is needed.
>If anyone has good ideas, please tell me.
>
>Thanks,
>Chao Fan





Re: [Qemu-devel] [for-2.9 2/5] pseries: Stubs for HPT resizing

2016-12-11 Thread David Gibson
On Fri, Dec 09, 2016 at 10:18:59AM +0100, Thomas Huth wrote:
> On 09.12.2016 10:09, David Gibson wrote:
> > On Fri, Dec 09, 2016 at 09:18:51AM +0100, Thomas Huth wrote:
> >> On 09.12.2016 03:23, David Gibson wrote:
> >>> This introduces stub implementations of the H_RESIZE_HPT_PREPARE and
> >>> H_RESIZE_HPT_COMMIT hypercalls which we hope to add in a PAPR
> >>> extension to allow run time resizing of a guest's hash page table.  It
> >>> also adds a new machine property for controlling whether this new
> >>> facility is available, and logic to check that against availability
> >>> with KVM (only supported with KVM PR for now).
> >>>
> >>> Finally, it adds a new string to the hypertas property in the device
> >>> tree, advertising to the guest the availability of the HPT resizing
> >>> hypercalls.  This is a tentative suggested value, and would need to be
> >>> standardized by PAPR before being merged.
> >>>
> >>> Signed-off-by: David Gibson 
> >>> ---
> >>>  hw/ppc/spapr.c | 66 
> >>> ++
> >>>  hw/ppc/spapr_hcall.c   | 36 +++
> >>>  hw/ppc/trace-events|  2 ++
> >>>  include/hw/ppc/spapr.h | 11 +
> >>>  target-ppc/kvm.c   | 26 
> >>>  target-ppc/kvm_ppc.h   |  5 
> >>>  6 files changed, 146 insertions(+)
> >>>
> >>> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> >>> index 0f25e83..ecb0822 100644
> >>> --- a/hw/ppc/spapr.c
> >>> +++ b/hw/ppc/spapr.c
> >>> @@ -760,6 +760,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, 
> >>> void *fdt)
> >>>  if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> >>>  add_str(hypertas, "hcall-multi-tce");
> >>>  }
> >>> +
> >>> +if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
> >>> +add_str(hypertas, "hcall-hpt-resize");
> >>> +}
> >>> +
> >>>  _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions",
> >>>   hypertas->str, hypertas->len));
> >>>  g_string_free(hypertas, TRUE);
> >>> @@ -1839,11 +1844,31 @@ static void ppc_spapr_init(MachineState *machine)
> >>>  long load_limit, fw_size;
> >>>  char *filename;
> >>>  int smt = kvmppc_smt_threads();
> >>> +Error *resize_hpt_err = NULL;
> >>>  
> >>>  msi_nonbroken = true;
> >>>  
> >>>  QLIST_INIT(&spapr->phbs);
> >>>  
> >>> +/* Check HPT resizing availability */
> >>> +kvmppc_check_papr_resize_hpt(&resize_hpt_err);
> >>> +if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) {
> >>> +if (resize_hpt_err) {
> >>> +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
> >>> +error_free(resize_hpt_err);
> >>> +resize_hpt_err = NULL;
> >>> +} else {
> >>> +spapr->resize_hpt = smc->resize_hpt_default;
> >>> +}
> >>> +}
> >>> +
> >>> +assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT);
> >>> +
> >>> +if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && 
> >>> resize_hpt_err) {
> >>> +error_report_err(resize_hpt_err);
> >>> +exit(1);
> >>> +}
> >>
> >> The logic here is IMHO a little bit hard to understand. Why do you need
> >> the SPAPR_RESIZE_HPT_DEFAULT state here at all? Wouldn't it be
> >> sufficient to start with SPAPR_RESIZE_HPT_DISABLED by default and to
> >> only enable it when the extension is available?
> > 
> > Because if the user explicitly sets something, we should never
> > override itin the logic here.  In order to determine whether the user
> > has set something explicitly, we need another value that means "not
> > set explicitly".
> 
> Hmm, ok, I think I slowly get it. Another question: Does this also take
> care of the handling if the user migrates from a machine that supports
> HPT resizing to a machine that does not support this feature?

Ok, so there are a fair few cases here.  The key point, though is that
even before now, we helpefully transferred the size of the HPT in the
migration stream before sending its contents (that was done so we
could update the sizing heuristics without breaking migration).

For TCG and KVM PR:

Here the ability to HPT resize depends purely on the qemu version.
Assuming this gets merged for qemu-2.9, pseries-2.9 TCG or PR guests
should always support resizing so that should be fine.

If you explicitly enabled HPT resizing for a pseries-2.8 guest running
under qemu-2.9 to an older qemu, then things could get odd.  The
destination guest would get an HPT of the size it had at the source at
the point of migration.  Any further attempts to resize would fail.
Given you have to explicitly set up this poor situation and the
failure mode isn't _that_ bad, I think that's ok.

For KVM HV:

Assuming we're migrating from a host kernel which can support resize
to one which can't:

If the resize-hpt is (explicitly) set differently on the the two ends
then, well, don't do that.  So assume it's the same on each end:

If resize-hpt=disabled, things are fine, obviously.

If resi

[Qemu-devel] [kvm-unit-tests PATCH v8 03/14] libcflat: introduce is_power_of_2()

2016-12-11 Thread Peter Xu
Suggested-by: Andrew Jones 
Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/libcflat.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index c622198..8455c3d 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -104,4 +104,9 @@ do {
\
}   \
 } while (0)
 
+static inline bool is_power_of_2(unsigned long n)
+{
+   return n && !(n & (n - 1));
+}
+
 #endif
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 02/14] x86/asm: add cpu_relax()

2016-12-11 Thread Peter Xu
This will be useful to be put inside loops.

Suggested-by: Andrew Jones 
Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/x86/asm/barrier.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/lib/x86/asm/barrier.h b/lib/x86/asm/barrier.h
index 7c108bd..193fb4c 100644
--- a/lib/x86/asm/barrier.h
+++ b/lib/x86/asm/barrier.h
@@ -13,4 +13,15 @@
 #define smp_rmb()  barrier()
 #define smp_wmb()  barrier()
 
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+   asm volatile("rep; nop" ::: "memory");
+}
+
+static inline void cpu_relax(void)
+{
+   rep_nop();
+}
+
 #endif
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 01/14] pci: fix missing extern for pci_testdev()

2016-12-11 Thread Peter Xu
Suggested-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/pci.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/pci.h b/lib/pci.h
index 30f5381..86d6b42 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -43,7 +43,7 @@ extern bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num);
 extern void pci_bar_print(pcidevaddr_t dev, int bar_num);
 extern void pci_dev_print_id(pcidevaddr_t dev);
 
-int pci_testdev(void);
+extern int pci_testdev(void);
 
 /*
  * pci-testdev is a driver for the pci-testdev qemu pci device. The
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 05/14] libcflat: add IS_ALIGNED() macro, and page sizes

2016-12-11 Thread Peter Xu
These macros will be useful to do page alignment checks.

Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/libcflat.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 8455c3d..88b10e2 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -33,6 +33,12 @@
 #define __ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
 #define __ALIGN(x, a)  __ALIGN_MASK(x, (typeof(x))(a) - 1)
 #define ALIGN(x, a)__ALIGN((x), (a))
+#define IS_ALIGNED(x, a)   (((x) & ((typeof(x))(a) - 1)) == 0)
+
+#define SZ_4K  (1 << 12)
+#define SZ_64K (1 << 16)
+#define SZ_2M  (1 << 21)
+#define SZ_1G  (1 << 30)
 
 typedef uint8_tu8;
 typedef int8_t s8;
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 04/14] x86: intel-iommu: add vt-d init test

2016-12-11 Thread Peter Xu
Adding fundamental init test for Intel IOMMU. This includes basic
initialization of Intel IOMMU device, like DMAR (DMA Remapping),
IR (Interrupt Remapping), QI (Queue Invalidation), etc.

Further tests can use vtd_init() to initialize Intel IOMMU environment.

x86/unittests is updated to add this test.

Signed-off-by: Peter Xu 
---
 lib/x86/intel-iommu.c |  99 +++
 lib/x86/intel-iommu.h | 141 ++
 x86/Makefile.x86_64   |   2 +
 x86/intel-iommu.c |  27 ++
 x86/unittests.cfg |   7 +++
 5 files changed, 276 insertions(+)
 create mode 100644 lib/x86/intel-iommu.c
 create mode 100644 lib/x86/intel-iommu.h
 create mode 100644 x86/intel-iommu.c

diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c
new file mode 100644
index 000..1887998
--- /dev/null
+++ b/lib/x86/intel-iommu.c
@@ -0,0 +1,99 @@
+/*
+ * Intel IOMMU APIs
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu ,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ */
+
+#include "intel-iommu.h"
+
+#define VTD_RTA_MASK  (PAGE_MASK)
+#define VTD_IRTA_MASK (PAGE_MASK)
+
+void *vtd_reg_base;
+
+static uint64_t vtd_root_table(void)
+{
+   /* No extend root table support yet */
+   return vtd_readq(DMAR_RTADDR_REG) & VTD_RTA_MASK;
+}
+
+static uint64_t vtd_ir_table(void)
+{
+   return vtd_readq(DMAR_IRTA_REG) & VTD_IRTA_MASK;
+}
+
+static void vtd_gcmd_or(uint32_t cmd)
+{
+   uint32_t status;
+
+   /* We only allow set one bit for each time */
+   assert(is_power_of_2(cmd));
+
+   status = vtd_readl(DMAR_GSTS_REG);
+   vtd_writel(DMAR_GCMD_REG, status | cmd);
+
+   if (cmd & VTD_GCMD_ONE_SHOT_BITS) {
+   /* One-shot bits are taking effect immediately */
+   return;
+   }
+
+   /* Make sure IOMMU handled our command request */
+   while (!(vtd_readl(DMAR_GSTS_REG) & cmd))
+   cpu_relax();
+}
+
+static void vtd_dump_init_info(void)
+{
+   uint32_t version;
+
+   version = vtd_readl(DMAR_VER_REG);
+
+   /* Major version >= 1 */
+   assert(((version >> 3) & 0xf) >= 1);
+
+   printf("VT-d version:   0x%x\n", version);
+   printf(" cap:   0x%016lx\n", vtd_readq(DMAR_CAP_REG));
+   printf(" ecap:  0x%016lx\n", vtd_readq(DMAR_ECAP_REG));
+}
+
+static void vtd_setup_root_table(void)
+{
+   void *root = alloc_page();
+
+   memset(root, 0, PAGE_SIZE);
+   vtd_writeq(DMAR_RTADDR_REG, virt_to_phys(root));
+   vtd_gcmd_or(VTD_GCMD_ROOT);
+   printf("DMAR table address: 0x%016lx\n", vtd_root_table());
+}
+
+static void vtd_setup_ir_table(void)
+{
+   void *root = alloc_page();
+
+   memset(root, 0, PAGE_SIZE);
+   /* 0xf stands for table size (2^(0xf+1) == 65536) */
+   vtd_writeq(DMAR_IRTA_REG, virt_to_phys(root) | 0xf);
+   vtd_gcmd_or(VTD_GCMD_IR_TABLE);
+   printf("IR table address: 0x%016lx\n", vtd_ir_table());
+}
+
+void vtd_init(void)
+{
+   setup_vm();
+   smp_init();
+
+   vtd_reg_base = ioremap(Q35_HOST_BRIDGE_IOMMU_ADDR, PAGE_SIZE);
+
+   vtd_dump_init_info();
+   vtd_gcmd_or(VTD_GCMD_QI); /* Enable QI */
+   vtd_setup_root_table();
+   vtd_setup_ir_table();
+   vtd_gcmd_or(VTD_GCMD_DMAR); /* Enable DMAR */
+   vtd_gcmd_or(VTD_GCMD_IR);   /* Enable IR */
+}
diff --git a/lib/x86/intel-iommu.h b/lib/x86/intel-iommu.h
new file mode 100644
index 000..92cc85f
--- /dev/null
+++ b/lib/x86/intel-iommu.h
@@ -0,0 +1,141 @@
+/*
+ * Intel IOMMU header
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu ,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ *
+ * (From include/linux/intel-iommu.h)
+ */
+
+#ifndef __INTEL_IOMMU_H__
+#define __INTEL_IOMMU_H__
+
+#include "libcflat.h"
+#include "vm.h"
+#include "isr.h"
+#include "smp.h"
+#include "desc.h"
+#include "asm/io.h"
+
+#define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
+
+/*
+ * Intel IOMMU register specification
+ */
+#define DMAR_VER_REG0x0  /* Arch version supported by this IOMMU */
+#define DMAR_CAP_REG0x8  /* Hardware supported capabilities */
+#define DMAR_CAP_REG_HI 0xc  /* High 32-bit of DMAR_CAP_REG */
+#define DMAR_ECAP_REG   0x10 /* Extended capabilities supported */
+#define DMAR_ECAP_REG_HI0X14
+#define DMAR_GCMD_REG   0x18 /* Global command */
+#define DMAR_GSTS_REG   0x1c /* Global status */
+#define DMAR_RTADDR_REG 0x20 /* Root entry table */
+#define DMAR_RTADDR_REG_HI  0X24
+#define DMAR_CCMD_REG   0x28 /* Context command */
+#define DMAR_CCMD_REG_HI0x2c
+#define DMAR_FSTS_REG   0x34 /* Fault status */
+#define DMAR_FECTL_REG  0x38 /* Fault control */
+#define DMAR_FEDATA_REG 0x3c /* Fault event interrupt data */
+#define DMAR_FEADDR_REG 0x40 /* Fault event 

[Qemu-devel] [kvm-unit-tests PATCH v8 00/14] VT-d unit test

2016-12-11 Thread Peter Xu
This is v8 of vt-d unit test series.

(CC qemu-devel list this time.)

Patch "libcflat: add IS_ALIGNED() macro, and page sizes" is picked up
by Drew in the ARM GIC framework series, so please feel free to drop
it when needed.

Online repo:

  https://github.com/xzpeter/kvm-unit-tests.git iommu-ut-v8

Please review. Thanks,

v8:
- use ioremap() to access vt-d/edu registers (adding vtd_reg_base to
  store vt-d mmio base register vaddr, and pci_edu_dev.reg_base to
  store edu device base register vaddr) [Alex]
- check vt-d version [Alex]
- vtd_install_pte: do phys_to_virt() for root pointer [Alex]
- renaming VTD_FETCH_VIRT_ADDR to VTD_PHYS_TO_VIRT [Alex]
- define VTD_PAGE_SHIFT and VTD_PAGE_SIZE, use them when necessary
  [Alex]
- change define of VTD_PTE_ADDR to cover bits 63:12

v7:
- patch 13: add r-b for Drew
- change type of dev_offset in edu_dma() into unsigned [Alex]
- squash Alex's fix (thanks) for ARM build into patch 08/14 [Alex]

v6:
- pci: rename pci_dev.bar to pcidev.resource (to Drew: I didn't remove
  your r-b in several patches due to this change, assuming the change
  is trivial) [Alex]
- pci_cap_walk(): add an assert to avoid dead loop [Alex]
- pci_cap_walk(): another assertion to make sure cap_id is valid
  [Drew]

v5:
- add one more patch at the beginning of series to add "extern" to
  pci_testdev() header definition [Drew]
- add "extern" to all pci.h functions [Drew]
- update IS_ALIGNED patch to be aligned with Drew's gic series [Drew]
- replace one more PCI_DEVFN_MAX/PCI_BAR_NUM in lib/pci-host-generic.c
  [Drew]
- add {} in vtd_install_pte() when there are one line code and one
  line comment [Drew]
- drop Drew's suggested-by in patch "x86: intel-iommu: add IR MSI
  test" (I forgot why I added it, but anyway let me drop it here...)
  [Drew]

v4:
(same as v3, but with correct patches sent out)

v3:
- is_power_of_2(): remove outer "()" [Drew]
- fix indent for vtd_root_table() [Drew]
- pci_find_dev(): keep {} to avoid touching more codes [Drew]
- pci_scan_bars(): check whether bar is 64bits [Drew]
- pci_enable_defaults(): make it return nothing [Drew]
- fix strnang blanks in lib/x86/intel-iommu.h [Drew]
- pci_setup_msi(): fix correct assert() inside [Drew]
- squash patches: 03+17 08+09 10+11 12+14 [Drew]
- remove all "()" for raw defines (numbers) in macros [Drew]

v2:
- move cpu_relax patch to the beginning, and use them in all places
[Drew]
- replace all corresponding 256 into PCI_DEVFN_MAX, as well for
PCI_BAR_NUM [Drew]
- adding is_power_of_2() to replace ONE_BIT_ONLY() [Drew]
- add SZ_64K macro [Drew]
- declare pci_config_write[wb] in lib/asm-generic/pci-host-bridge.h [Alex]
- edu_reg_read/write() add "l" in func name [Drew]
- drop pci_set_master(), instead, provide pci_cmd_set_clr() [Drew]
- change return code into bool (always) for functions that apply
[Drew]
- keep old pci_find_dev() interface [Drew/Alex]
- use __raw_{read|write}*() for both vt-d and edu register read/writes
[Alex]
- remove pci_ prefix for all pci_dev fields [Drew]
- replace 0xff in cap_handlers[0xff] into (PCI_CAP_ID_MAX + 1) [Drew]
- make x86/unittest.cfg simpler by using q35 directly with eim=off
[Drew]

RFC -> v1:
- when init edu device fail, report_skip() rather than return error
[Radim]
- use asserts rather than "static bool inited" to avoid multiple init
of components (affects patch 1/2) [Drew]
- moving the first two patches out of the series [Drew]
- int vtd_init(), do not setup_idt() since smp_init() did it [Drew]
- when edu do not have MSI enabled, skip interrupt test [Radim]
- rename vtd_reg_*() into vtd_{read|write}[lq](), and move them to
header file [Drew]
- use PAGE_MASK when able [Drew]
- use "&" instead of "|" in intel-iommu init test (three places)
[Drew]
- use "vtd_init()" in unit test [Drew]
- mention that where intel-iommu.h comes from [Drew]
- re-written vtd_gcmd_or(), make it also work on even hardware [Drew]
- remove most of the oneline wrapper for VT-d registers, instead, use
vtd_{read|write}* with register names [Drew]
- remove useless BDF helpers [Drew]
- move edu device macros into header file [Drew]
- make edu_check_alive static inline [Drew]
- remove all useless wrappers in pci-edu.c [Drew]
- remove pci_dma_dir_t and all its users, instead, use "bool
from_device" [Drew]
- not use typedef for structs, to follow Linux/kvm-unit-tests coding
style [Drew]
- let pci_dev_init() clean and simple, then provide
pci_enable_defaults() for more complicated things [Drew]
- add one more patch to add intel-iommu test into x86/unittest [Radim]
- use 0x60 intr request instead of factorial to trigger edu device
interrupt [Drew]
- ...and some other changes I just forgot to note down...

Currently only a very small test scope is covered:

* VT-d init
* DMAR: 4 bytes copy
* IR: MSI

However this series could be a base point to add more test cases for
VT-d. The problem is, there are many IOMMU error conditions which are
very hard to be triggered in a real guest (IOMMU has merely no
interface for guest user, 

[Qemu-devel] [kvm-unit-tests PATCH v8 08/14] pci: introduce struct pci_dev

2016-12-11 Thread Peter Xu
To extend current PCI framework, we need a per-device struct to store
device specific information. Time to have a pci_dev struct. Most of the
current PCI APIs are converted to use this pci_dev object as the first
argument. Currently it only contains one field "bdf", which is the bdf
of current device.

For a few APIs like pci_config_*() ops or pci_find_dev(), I kept the old
interface (use PCI BDF value rather than "struct pci_dev") since they
can be used in a open context that without any specific PCI device.

Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/pci-host-generic.c | 17 ---
 lib/pci-testdev.c  | 10 +
 lib/pci.c  | 56 ++
 lib/pci.h  | 24 ++
 x86/vmexit.c   | 18 
 5 files changed, 76 insertions(+), 49 deletions(-)

diff --git a/lib/pci-host-generic.c b/lib/pci-host-generic.c
index 6ac0f15..958ef70 100644
--- a/lib/pci-host-generic.c
+++ b/lib/pci-host-generic.c
@@ -165,7 +165,7 @@ static struct pci_host_bridge *pci_dt_probe(void)
return host;
 }
 
-static bool pci_alloc_resource(pcidevaddr_t dev, int bar_num, u64 *addr)
+static bool pci_alloc_resource(struct pci_dev *dev, int bar_num, u64 *addr)
 {
struct pci_host_bridge *host = pci_host_bridge;
struct pci_addr_space *as = &host->addr_space[0];
@@ -192,7 +192,7 @@ static bool pci_alloc_resource(pcidevaddr_t dev, int 
bar_num, u64 *addr)
 
if (i >= host->nr_addr_spaces) {
printf("%s: warning: can't satisfy request for ", __func__);
-   pci_dev_print_id(dev);
+   pci_dev_print_id(dev->bdf);
printf(" ");
pci_bar_print(dev, bar_num);
printf("\n");
@@ -211,6 +211,7 @@ static bool pci_alloc_resource(pcidevaddr_t dev, int 
bar_num, u64 *addr)
 
 bool pci_probe(void)
 {
+   struct pci_dev pci_dev;
pcidevaddr_t dev;
u8 header;
u32 cmd;
@@ -221,10 +222,12 @@ bool pci_probe(void)
if (!pci_host_bridge)
return false;
 
-   for (dev = 0; dev < 256; dev++) {
+   for (dev = 0; dev < PCI_DEVFN_MAX; dev++) {
if (!pci_dev_exists(dev))
continue;
 
+   pci_dev_init(&pci_dev, dev);
+
/* We are only interested in normal PCI devices */
header = pci_config_readb(dev, PCI_HEADER_TYPE);
if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL)
@@ -235,16 +238,16 @@ bool pci_probe(void)
for (i = 0; i < 6; i++) {
u64 addr;
 
-   if (pci_alloc_resource(dev, i, &addr)) {
-   pci_bar_set_addr(dev, i, addr);
+   if (pci_alloc_resource(&pci_dev, i, &addr)) {
+   pci_bar_set_addr(&pci_dev, i, addr);
 
-   if (pci_bar_is_memory(dev, i))
+   if (pci_bar_is_memory(&pci_dev, i))
cmd |= PCI_COMMAND_MEMORY;
else
cmd |= PCI_COMMAND_IO;
}
 
-   if (pci_bar_is64(dev, i))
+   if (pci_bar_is64(&pci_dev, i))
i++;
}
 
diff --git a/lib/pci-testdev.c b/lib/pci-testdev.c
index ad482d3..7d298e6 100644
--- a/lib/pci-testdev.c
+++ b/lib/pci-testdev.c
@@ -163,9 +163,10 @@ static int pci_testdev_all(struct pci_test_dev_hdr *test,
 
 int pci_testdev(void)
 {
+   struct pci_dev pci_dev;
+   pcidevaddr_t dev;
phys_addr_t addr;
void __iomem *mem, *io;
-   pcidevaddr_t dev;
int nr_tests = 0;
bool ret;
 
@@ -175,14 +176,15 @@ int pci_testdev(void)
   "check QEMU '-device pci-testdev' parameter\n");
return -1;
}
+   pci_dev_init(&pci_dev, dev);
 
-   ret = pci_bar_is_valid(dev, 0) && pci_bar_is_valid(dev, 1);
+   ret = pci_bar_is_valid(&pci_dev, 0) && pci_bar_is_valid(&pci_dev, 1);
assert(ret);
 
-   addr = pci_bar_get_addr(dev, 0);
+   addr = pci_bar_get_addr(&pci_dev, 0);
mem = ioremap(addr, PAGE_SIZE);
 
-   addr = pci_bar_get_addr(dev, 1);
+   addr = pci_bar_get_addr(&pci_dev, 1);
io = (void *)(unsigned long)addr;
 
nr_tests += pci_testdev_all(mem, &pci_testdev_mem_ops);
diff --git a/lib/pci.c b/lib/pci.c
index 6bd54cb..8f2356d 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -13,12 +13,18 @@ bool pci_dev_exists(pcidevaddr_t dev)
pci_config_readw(dev, PCI_DEVICE_ID) != 0x);
 }
 
+void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf)
+{
+   memset(dev, 0, sizeof(*dev));
+   dev->bdf = bdf;
+}
+
 /* Scan bus look for a specific device. Only bus 0 scanned for now. */
 pcidevaddr_t pci_find_dev(uint16_t

[Qemu-devel] [kvm-unit-tests PATCH v8 10/14] pci: provide pci_enable_defaults()

2016-12-11 Thread Peter Xu
One helper function to set/clear specific bit in PCI_COMMAND register is
introduced. Then, provide a function to do most of the common PCI init
work.

Suggested-by: Andrew Jones 
Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/pci.c | 19 +++
 lib/pci.h |  2 ++
 2 files changed, 21 insertions(+)

diff --git a/lib/pci.c b/lib/pci.c
index d4521be..bf2a3df 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -7,6 +7,18 @@
 #include "pci.h"
 #include "asm/pci.h"
 
+void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr)
+{
+   uint16_t val = pci_config_readw(dev->bdf, PCI_COMMAND);
+
+   /* No overlap is allowed */
+   assert((set & clr) == 0);
+   val |= set;
+   val &= ~clr;
+
+   pci_config_writew(dev->bdf, PCI_COMMAND, val);
+}
+
 bool pci_dev_exists(pcidevaddr_t dev)
 {
return (pci_config_readw(dev, PCI_VENDOR_ID) != 0x &&
@@ -242,3 +254,10 @@ void pci_scan_bars(struct pci_dev *dev)
}
}
 }
+
+void pci_enable_defaults(struct pci_dev *dev)
+{
+   pci_scan_bars(dev);
+   /* Enable device DMA operations */
+   pci_cmd_set_clr(dev, PCI_COMMAND_MASTER, 0);
+}
diff --git a/lib/pci.h b/lib/pci.h
index 8215c9d..d3052ef 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -25,6 +25,8 @@ struct pci_dev {
 
 extern void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf);
 extern void pci_scan_bars(struct pci_dev *dev);
+extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr);
+extern void pci_enable_defaults(struct pci_dev *dev);
 
 extern bool pci_probe(void);
 extern void pci_print(void);
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 06/14] libcflat: moving MIN/MAX here

2016-12-11 Thread Peter Xu
That's something can be used outside alloc.c.

Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/alloc.c| 3 ---
 lib/libcflat.h | 3 +++
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/alloc.c b/lib/alloc.c
index e1d7b8a..58af52b 100644
--- a/lib/alloc.c
+++ b/lib/alloc.c
@@ -7,9 +7,6 @@
 #include "asm/spinlock.h"
 #include "asm/io.h"
 
-#define MIN(a, b)  ((a) < (b) ? (a) : (b))
-#define MAX(a, b)  ((a) > (b) ? (a) : (b))
-
 #define PHYS_ALLOC_NR_REGIONS  256
 
 struct phys_alloc_region {
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 88b10e2..94d2a53 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -40,6 +40,9 @@
 #define SZ_2M  (1 << 21)
 #define SZ_1G  (1 << 30)
 
+#define MIN(a, b)  ((a) < (b) ? (a) : (b))
+#define MAX(a, b)  ((a) > (b) ? (a) : (b))
+
 typedef uint8_tu8;
 typedef int8_t s8;
 typedef uint16_t   u16;
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 09/14] pci: provide pci_scan_bars()

2016-12-11 Thread Peter Xu
Let's provide a more general way to scan PCI bars, rather than read the
config registers every time.

Then let x86/vmexit.c leverage pci_scan_bars()

Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/pci-host-generic.c |  2 +-
 lib/pci.c  | 17 -
 lib/pci.h  |  5 +
 x86/vmexit.c   | 17 ++---
 4 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/lib/pci-host-generic.c b/lib/pci-host-generic.c
index 958ef70..b1d2fc5 100644
--- a/lib/pci-host-generic.c
+++ b/lib/pci-host-generic.c
@@ -235,7 +235,7 @@ bool pci_probe(void)
 
cmd = PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
 
-   for (i = 0; i < 6; i++) {
+   for (i = 0; i < PCI_BAR_NUM; i++) {
u64 addr;
 
if (pci_alloc_resource(&pci_dev, i, &addr)) {
diff --git a/lib/pci.c b/lib/pci.c
index 8f2356d..d4521be 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -207,7 +207,7 @@ static void pci_dev_print(pcidevaddr_t dev)
if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL)
return;
 
-   for (i = 0; i < 6; i++) {
+   for (i = 0; i < PCI_BAR_NUM; i++) {
if (pci_bar_size(&pci_dev, i)) {
printf("\t");
pci_bar_print(&pci_dev, i);
@@ -227,3 +227,18 @@ void pci_print(void)
pci_dev_print(dev);
}
 }
+
+void pci_scan_bars(struct pci_dev *dev)
+{
+   int i;
+
+   for (i = 0; i < PCI_BAR_NUM; i++) {
+   if (!pci_bar_is_valid(dev, i))
+   continue;
+   dev->resource[i] = pci_bar_get_addr(dev, i);
+   if (pci_bar_is64(dev, i)) {
+   i++;
+   dev->resource[i] = (phys_addr_t)0;
+   }
+   }
+}
diff --git a/lib/pci.h b/lib/pci.h
index 355acd0..8215c9d 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -15,13 +15,16 @@ enum {
PCIDEVADDR_INVALID = 0x,
 };
 
+#define PCI_BAR_NUM 6
 #define PCI_DEVFN_MAX   256
 
 struct pci_dev {
uint16_t bdf;
+   phys_addr_t resource[PCI_BAR_NUM];
 };
 
 extern void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf);
+extern void pci_scan_bars(struct pci_dev *dev);
 
 extern bool pci_probe(void);
 extern void pci_print(void);
@@ -65,6 +68,8 @@ extern int pci_testdev(void);
  * pci-testdev supports at least three types of tests (via mmio and
  * portio BARs): no-eventfd, wildcard-eventfd and datamatch-eventfd
  */
+#define PCI_TESTDEV_BAR_MEM0
+#define PCI_TESTDEV_BAR_IO 1
 #define PCI_TESTDEV_NUM_BARS   2
 #define PCI_TESTDEV_NUM_TESTS  3
 
diff --git a/x86/vmexit.c b/x86/vmexit.c
index 63fa070..f9a22de 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -389,17 +389,12 @@ int main(int ac, char **av)
ret = pci_find_dev(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_TEST);
if (ret != PCIDEVADDR_INVALID) {
pci_dev_init(&pcidev, ret);
-   for (i = 0; i < PCI_TESTDEV_NUM_BARS; i++) {
-   if (!pci_bar_is_valid(&pcidev, i)) {
-   continue;
-   }
-   if (pci_bar_is_memory(&pcidev, i)) {
-   membar = pci_bar_get_addr(&pcidev, i);
-   pci_test.memaddr = ioremap(membar, PAGE_SIZE);
-   } else {
-   pci_test.iobar = pci_bar_get_addr(&pcidev, i);
-   }
-   }
+   pci_scan_bars(&pcidev);
+   assert(pci_bar_is_memory(&pcidev, PCI_TESTDEV_BAR_MEM));
+   assert(!pci_bar_is_memory(&pcidev, PCI_TESTDEV_BAR_IO));
+   membar = pcidev.resource[PCI_TESTDEV_BAR_MEM];
+   pci_test.memaddr = ioremap(membar, PAGE_SIZE);
+   pci_test.iobar = pcidev.resource[PCI_TESTDEV_BAR_IO];
printf("pci-testdev at 0x%x membar %lx iobar %x\n",
   pcidev.bdf, membar, pci_test.iobar);
}
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 07/14] vm/page: provide PGDIR_OFFSET() macro

2016-12-11 Thread Peter Xu
This can be used in further patches.

Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/x86/asm/page.h | 3 +++
 lib/x86/vm.c   | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/x86/asm/page.h b/lib/x86/asm/page.h
index 5044a49..c43bab2 100644
--- a/lib/x86/asm/page.h
+++ b/lib/x86/asm/page.h
@@ -41,5 +41,8 @@
 #definePGDIR_MASK  1023
 #endif
 
+#define PGDIR_BITS(lvl)(((lvl) - 1) * PGDIR_WIDTH + PAGE_SHIFT)
+#define PGDIR_OFFSET(va, lvl)  (((va) >> PGDIR_BITS(lvl)) & PGDIR_MASK)
+
 #endif /* !__ASSEMBLY__ */
 #endif
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index f7e778b..cda4c5f 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -48,7 +48,7 @@ unsigned long *install_pte(unsigned long *cr3,
 unsigned offset;
 
 for (level = PAGE_LEVEL; level > pte_level; --level) {
-   offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & 
PGDIR_MASK;
+   offset = PGDIR_OFFSET((unsigned long)virt, level);
if (!(pt[offset] & PT_PRESENT_MASK)) {
unsigned long *new_pt = pt_page;
 if (!new_pt)
@@ -60,7 +60,7 @@ unsigned long *install_pte(unsigned long *cr3,
}
pt = phys_to_virt(pt[offset] & PT_ADDR_MASK);
 }
-offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & 
PGDIR_MASK;
+offset = PGDIR_OFFSET((unsigned long)virt, level);
 pt[offset] = pte;
 return &pt[offset];
 }
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 11/14] pci: edu: introduce pci-edu helpers

2016-12-11 Thread Peter Xu
QEMU edu device is a pci device that is originally written for
educational purpose, however it also suits for IOMMU unit test. Adding
helpers for this specific device to implement the device logic.

The device supports lots of functions, here only DMA operation is
supported.

The spec of the device can be found at:

  https://github.com/qemu/qemu/blob/master/docs/specs/edu.txt

Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/pci-edu.c | 73 
 lib/pci-edu.h | 83 +++
 2 files changed, 156 insertions(+)
 create mode 100644 lib/pci-edu.c
 create mode 100644 lib/pci-edu.h

diff --git a/lib/pci-edu.c b/lib/pci-edu.c
new file mode 100644
index 000..8096470
--- /dev/null
+++ b/lib/pci-edu.c
@@ -0,0 +1,73 @@
+/*
+ * Edu PCI device.
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu ,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ */
+
+#include "pci-edu.h"
+#include "asm/barrier.h"
+
+/* Return true if alive */
+static inline bool edu_check_alive(struct pci_edu_dev *dev)
+{
+   static uint32_t live_count = 1;
+   uint32_t value;
+
+   edu_reg_writel(dev, EDU_REG_ALIVE, live_count++);
+   value = edu_reg_readl(dev, EDU_REG_ALIVE);
+   return (live_count - 1 == ~value);
+}
+
+bool edu_init(struct pci_edu_dev *dev)
+{
+   pcidevaddr_t dev_addr;
+
+   dev_addr = pci_find_dev(PCI_VENDOR_ID_QEMU, PCI_DEVICE_ID_EDU);
+   if (dev_addr == PCIDEVADDR_INVALID)
+   return false;
+
+   pci_dev_init(&dev->pci_dev, dev_addr);
+   pci_enable_defaults(&dev->pci_dev);
+   dev->reg_base = ioremap(dev->pci_dev.resource[EDU_BAR], PAGE_SIZE);
+   assert(edu_check_alive(dev));
+   return true;
+}
+
+void edu_dma(struct pci_edu_dev *dev, iova_t iova,
+size_t size, unsigned int dev_offset, bool from_device)
+{
+   uint64_t from, to;
+   uint32_t cmd = EDU_CMD_DMA_START;
+
+   assert(size <= EDU_DMA_SIZE_MAX);
+   assert(dev_offset < EDU_DMA_SIZE_MAX);
+
+   printf("edu device DMA start %s addr %p size 0x%lu off 0x%x\n",
+  from_device ? "FROM" : "TO",
+  (void *)iova, size, dev_offset);
+
+   if (from_device) {
+   from = dev_offset + EDU_DMA_START;
+   to = iova;
+   cmd |= EDU_CMD_DMA_FROM;
+   } else {
+   from = iova;
+   to = EDU_DMA_START + dev_offset;
+   cmd |= EDU_CMD_DMA_TO;
+   }
+
+   edu_reg_writeq(dev, EDU_REG_DMA_SRC, from);
+   edu_reg_writeq(dev, EDU_REG_DMA_DST, to);
+   edu_reg_writeq(dev, EDU_REG_DMA_COUNT, size);
+   edu_reg_writel(dev, EDU_REG_DMA_CMD, cmd);
+
+   /* Wait until DMA finished */
+   while (edu_reg_readl(dev, EDU_REG_DMA_CMD) & EDU_CMD_DMA_START)
+   cpu_relax();
+}
diff --git a/lib/pci-edu.h b/lib/pci-edu.h
new file mode 100644
index 000..8395ebe
--- /dev/null
+++ b/lib/pci-edu.h
@@ -0,0 +1,83 @@
+/*
+ * Edu PCI device header.
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu ,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ *
+ * Edu device is a virtualized device in QEMU. Please refer to
+ * docs/specs/edu.txt in QEMU repository for EDU device manual.
+ */
+#ifndef __PCI_EDU_H__
+#define __PCI_EDU_H__
+
+#include "pci.h"
+#include "asm/io.h"
+
+#define  PCI_VENDOR_ID_QEMU  0x1234
+#define  PCI_DEVICE_ID_EDU   0x11e8
+
+/* The only bar used by EDU device */
+#define EDU_BAR 0
+#define EDU_MAGIC   0xed
+#define EDU_VERSION 0x100
+#define EDU_DMA_BUF_SIZE(1 << 20)
+#define EDU_INPUT_BUF_SIZE  256
+
+#define EDU_REG_ID  0x0
+#define EDU_REG_ALIVE   0x4
+#define EDU_REG_FACTORIAL   0x8
+#define EDU_REG_STATUS  0x20
+#define EDU_REG_DMA_SRC 0x80
+#define EDU_REG_DMA_DST 0x88
+#define EDU_REG_DMA_COUNT   0x90
+#define EDU_REG_DMA_CMD 0x98
+
+#define EDU_CMD_DMA_START   0x01
+#define EDU_CMD_DMA_FROM0x02
+#define EDU_CMD_DMA_TO  0x00
+
+#define EDU_STATUS_FACTORIAL0x1
+#define EDU_STATUS_INT_ENABLE   0x80
+
+#define EDU_DMA_START   0x4
+#define EDU_DMA_SIZE_MAX4096
+
+struct pci_edu_dev {
+   struct pci_dev pci_dev;
+   volatile void *reg_base;
+};
+
+#define edu_reg(d, r) (volatile void *)((d)->reg_base + (r))
+
+static inline uint64_t edu_reg_readq(struct pci_edu_dev *dev, int reg)
+{
+   return __raw_readq(edu_reg(dev, reg));
+}
+
+static inline uint32_t edu_reg_readl(struct pci_edu_dev *dev, int reg)
+{
+   return __raw_readl(edu_reg(dev, reg));
+}
+
+static inline void edu_reg_writeq(struct pci_edu_dev *dev, int reg,
+ 

[Qemu-devel] [kvm-unit-tests PATCH v8 12/14] x86: intel-iommu: add dmar test

2016-12-11 Thread Peter Xu
DMAR test is based on QEMU edu device. A 4B DMA memory copy is carried
out as the simplest DMAR test.

Signed-off-by: Peter Xu 
---
 lib/pci.h |   5 ++
 lib/x86/intel-iommu.c | 133 ++
 lib/x86/intel-iommu.h |   4 ++
 x86/Makefile.common   |   1 +
 x86/intel-iommu.c |  51 +++
 5 files changed, 194 insertions(+)

diff --git a/lib/pci.h b/lib/pci.h
index d3052ef..26968b1 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -18,6 +18,9 @@ enum {
 #define PCI_BAR_NUM 6
 #define PCI_DEVFN_MAX   256
 
+#define PCI_BDF_GET_DEVFN(x)((x) & 0xff)
+#define PCI_BDF_GET_BUS(x)  (((x) >> 8) & 0xff)
+
 struct pci_dev {
uint16_t bdf;
phys_addr_t resource[PCI_BAR_NUM];
@@ -28,6 +31,8 @@ extern void pci_scan_bars(struct pci_dev *dev);
 extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr);
 extern void pci_enable_defaults(struct pci_dev *dev);
 
+typedef phys_addr_t iova_t;
+
 extern bool pci_probe(void);
 extern void pci_print(void);
 extern bool pci_dev_exists(pcidevaddr_t dev);
diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c
index 1887998..86b1805 100644
--- a/lib/x86/intel-iommu.c
+++ b/lib/x86/intel-iommu.c
@@ -11,6 +11,42 @@
  */
 
 #include "intel-iommu.h"
+#include "libcflat.h"
+
+/*
+ * VT-d in QEMU currently only support 39 bits address width, which is
+ * 3-level translation.
+ */
+#define VTD_PAGE_LEVEL  3
+#define VTD_CE_AW_39BIT 0x1
+
+typedef uint64_t vtd_pte_t;
+
+struct vtd_root_entry {
+   /* Quad 1 */
+   uint64_t present:1;
+   uint64_t __reserved:11;
+   uint64_t context_table_p:52;
+   /* Quad 2 */
+   uint64_t __reserved_2;
+} __attribute__ ((packed));
+typedef struct vtd_root_entry vtd_re_t;
+
+struct vtd_context_entry {
+   /* Quad 1 */
+   uint64_t present:1;
+   uint64_t disable_fault_report:1;
+   uint64_t trans_type:2;
+   uint64_t __reserved:8;
+   uint64_t slptptr:52;
+   /* Quad 2 */
+   uint64_t addr_width:3;
+   uint64_t __ignore:4;
+   uint64_t __reserved_2:1;
+   uint64_t domain_id:16;
+   uint64_t __reserved_3:40;
+} __attribute__ ((packed));
+typedef struct vtd_context_entry vtd_ce_t;
 
 #define VTD_RTA_MASK  (PAGE_MASK)
 #define VTD_IRTA_MASK (PAGE_MASK)
@@ -83,6 +119,103 @@ static void vtd_setup_ir_table(void)
printf("IR table address: 0x%016lx\n", vtd_ir_table());
 }
 
+static void vtd_install_pte(vtd_pte_t *root, iova_t iova,
+   phys_addr_t pa, int level_target)
+{
+   int level;
+   unsigned int offset;
+   void *page;
+
+   for (level = VTD_PAGE_LEVEL; level > level_target; level--) {
+   offset = PGDIR_OFFSET(iova, level);
+   if (!(root[offset] & VTD_PTE_RW)) {
+   page = alloc_page();
+   memset(page, 0, PAGE_SIZE);
+   root[offset] = virt_to_phys(page) | VTD_PTE_RW;
+   }
+   root = (uint64_t *)(phys_to_virt(root[offset] &
+VTD_PTE_ADDR));
+   }
+
+   offset = PGDIR_OFFSET(iova, level);
+   root[offset] = pa | VTD_PTE_RW;
+   if (level != 1) {
+   /* This is huge page */
+   root[offset] |= VTD_PTE_HUGE;
+   }
+}
+
+#define  VTD_PHYS_TO_VIRT(x) \
+   ((void *)(((uint64_t)phys_to_virt(x)) >> VTD_PAGE_SHIFT))
+
+/**
+ * vtd_map_range: setup IO address mapping for specific memory range
+ *
+ * @sid: source ID of the device to setup
+ * @iova: start IO virtual address
+ * @pa: start physical address
+ * @size: size of the mapping area
+ */
+void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t pa, size_t size)
+{
+   uint8_t bus_n, devfn;
+   void *slptptr;
+   vtd_ce_t *ce;
+   vtd_re_t *re = phys_to_virt(vtd_root_table());
+
+   assert(IS_ALIGNED(iova, SZ_4K));
+   assert(IS_ALIGNED(pa, SZ_4K));
+   assert(IS_ALIGNED(size, SZ_4K));
+
+   bus_n = PCI_BDF_GET_BUS(sid);
+   devfn = PCI_BDF_GET_DEVFN(sid);
+
+   /* Point to the correct root entry */
+   re += bus_n;
+
+   if (!re->present) {
+   ce = alloc_page();
+   memset(ce, 0, PAGE_SIZE);
+   memset(re, 0, sizeof(*re));
+   re->context_table_p = virt_to_phys(ce) >> VTD_PAGE_SHIFT;
+   re->present = 1;
+   printf("allocated vt-d root entry for PCI bus %d\n",
+  bus_n);
+   } else
+   ce = VTD_PHYS_TO_VIRT(re->context_table_p);
+
+   /* Point to the correct context entry */
+   ce += devfn;
+
+   if (!ce->present) {
+   slptptr = alloc_page();
+   memset(slptptr, 0, PAGE_SIZE);
+   memset(ce, 0, sizeof(*ce));
+   /* To make it simple, domain ID is the same as SID */
+   ce->domain_id = sid;
+ 

Re: [Qemu-devel] [PATCH for-2.9 v2] virtio-crypto: zeroize the key material before free

2016-12-11 Thread Gonglei (Arei)


> -Original Message-
> From: Michael S. Tsirkin [mailto:m...@redhat.com]
> Sent: Sunday, December 11, 2016 10:51 AM
> To: Eric Blake
> Cc: Gonglei (Arei); qemu-devel@nongnu.org; stefa...@redhat.com
> Subject: Re: [PATCH for-2.9 v2] virtio-crypto: zeroize the key material before
> free
> 
> On Thu, Dec 08, 2016 at 09:20:07AM -0600, Eric Blake wrote:
> > On 12/07/2016 08:33 PM, Gonglei (Arei) wrote:
> >
> > >> Sensitive information is sometimes also held in mlocked pages to prevent
> > >> it being swapped to disk, but qemu in general is not currently taking
> > >> that level of precaution (see also commit 8813800b).
> > >>
> > >>>
> > >>> Let's zeroize the memory of CryptoDevBackendSymOpInfo structure
> pointed
> > >>> for key material security.
> > >>>
> > >>> [v2: Stefan perfects the commit message, thanks]
> > >>
> > >> The v2 blurb should appear after the --- line, as it is nice for
> > >> reviewers but a year from now when reading 'git log' we won't care how
> > >> many versions were on the list, only about the one version in git.
> > >>
> > > Yes, you are right. I just wanted to keep the Stefan's work because
> > > the most of commit message comes from him. :)
> >
> > Then I might have written:
> >
> > [Thanks to Stefan for help with crafting the commit message]
> >
> > >
> > >>> Signed-off-by: Gonglei 
> > >>> Reviewed-by: Stefan Hajnoczi 
> > >>> ---
> > >>>  hw/virtio/virtio-crypto.c | 13 -
> > >>>  1 file changed, 12 insertions(+), 1 deletion(-)
> > >>>
> > >>
> > >> The commit message may still need improvement, but the maintainer
> might
> > >> be willing to do that without needing a v3.  At any rate,
> > >> Reviewed-by: Eric Blake 
> > >>
> > > Thanks.
> >
> > We'll see what the maintainer thinks :)
> >
> > --
> > Eric Blake   eblake redhat com+1-919-301-3266
> > Libvirt virtualization library http://libvirt.org
> >
> 
> I'd suggest post v3 after 2.8 is out.
> 
OK, will do.


Regards,
-Gonglei



[Qemu-devel] [kvm-unit-tests PATCH v8 13/14] pci: add msi support for 32/64bit address

2016-12-11 Thread Peter Xu
pci_cap_walk() is provided to allow walk through all the capability bits
for a specific PCI device. If a cap handler is provided, it'll be
triggered if the cap is detected along the cap walk.

MSI cap handler is the first one supported. We can add more cap handler
in the future.

Meanwhile, pci_setup_msi() API is provided to support basic 32/64 bit
address MSI setup.

Reviewed-by: Andrew Jones 
Signed-off-by: Peter Xu 
---
 lib/pci.c | 69 +++
 lib/pci.h |  4 
 2 files changed, 73 insertions(+)

diff --git a/lib/pci.c b/lib/pci.c
index bf2a3df..a51eb8e 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -7,6 +7,74 @@
 #include "pci.h"
 #include "asm/pci.h"
 
+typedef void (*pci_cap_handler)(struct pci_dev *dev, int cap_offset);
+
+static void pci_cap_msi_handler(struct pci_dev *dev, int cap_offset)
+{
+   printf("Detected MSI for device 0x%x offset 0x%x\n",
+  dev->bdf, cap_offset);
+   dev->msi_offset = cap_offset;
+}
+
+static pci_cap_handler cap_handlers[PCI_CAP_ID_MAX + 1] = {
+   [PCI_CAP_ID_MSI] = pci_cap_msi_handler,
+};
+
+void pci_cap_walk(struct pci_dev *dev)
+{
+   uint8_t cap_offset;
+   uint8_t cap_id;
+   int count = 0;
+
+   cap_offset = pci_config_readb(dev->bdf, PCI_CAPABILITY_LIST);
+   while (cap_offset) {
+   cap_id = pci_config_readb(dev->bdf, cap_offset);
+   printf("PCI detected cap 0x%x\n", cap_id);
+   assert(cap_id < PCI_CAP_ID_MAX + 1);
+   if (cap_handlers[cap_id])
+   cap_handlers[cap_id](dev, cap_offset);
+   cap_offset = pci_config_readb(dev->bdf, cap_offset + 1);
+   /* Avoid dead loop during cap walk */
+   assert(++count <= 255);
+   }
+}
+
+bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr, uint32_t msi_data)
+{
+   uint16_t msi_control;
+   uint16_t offset;
+   pcidevaddr_t addr;
+
+   assert(dev);
+
+   if (!dev->msi_offset) {
+   printf("MSI: dev 0x%x does not support MSI.\n", dev->bdf);
+   return false;
+   }
+
+   addr = dev->bdf;
+   offset = dev->msi_offset;
+   msi_control = pci_config_readw(addr, offset + PCI_MSI_FLAGS);
+   pci_config_writel(addr, offset + PCI_MSI_ADDRESS_LO,
+ msi_addr & 0x);
+
+   if (msi_control & PCI_MSI_FLAGS_64BIT) {
+   pci_config_writel(addr, offset + PCI_MSI_ADDRESS_HI,
+ (uint32_t)(msi_addr >> 32));
+   pci_config_writel(addr, offset + PCI_MSI_DATA_64, msi_data);
+   printf("MSI: dev 0x%x init 64bit address: ", addr);
+   } else {
+   pci_config_writel(addr, offset + PCI_MSI_DATA_32, msi_data);
+   printf("MSI: dev 0x%x init 32bit address: ", addr);
+   }
+   printf("addr=0x%lx, data=0x%x\n", msi_addr, msi_data);
+
+   msi_control |= PCI_MSI_FLAGS_ENABLE;
+   pci_config_writew(addr, offset + PCI_MSI_FLAGS, msi_control);
+
+   return true;
+}
+
 void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr)
 {
uint16_t val = pci_config_readw(dev->bdf, PCI_COMMAND);
@@ -260,4 +328,5 @@ void pci_enable_defaults(struct pci_dev *dev)
pci_scan_bars(dev);
/* Enable device DMA operations */
pci_cmd_set_clr(dev, PCI_COMMAND_MASTER, 0);
+   pci_cap_walk(dev);
 }
diff --git a/lib/pci.h b/lib/pci.h
index 26968b1..e71a05d 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -23,13 +23,17 @@ enum {
 
 struct pci_dev {
uint16_t bdf;
+   uint16_t msi_offset;
phys_addr_t resource[PCI_BAR_NUM];
 };
 
 extern void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf);
 extern void pci_scan_bars(struct pci_dev *dev);
 extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr);
+extern void pci_cap_walk(struct pci_dev *dev);
 extern void pci_enable_defaults(struct pci_dev *dev);
+extern bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr,
+ uint32_t msi_data);
 
 typedef phys_addr_t iova_t;
 
-- 
2.7.4




[Qemu-devel] [kvm-unit-tests PATCH v8 14/14] x86: intel-iommu: add IR MSI test

2016-12-11 Thread Peter Xu
First of all, vtd_setup_msi() is provided. It setup IRTE entries,
meanwhile, setup PCI device MSI vectors corresponding to VT-d spec.

Meanwhile, IR MSI test is added to intel IOMMU unit test. The basic IR
test is carried out by a edu INTR raise request. When write to the intr
raise register, interrupt will be generated. Type of interrupt will
depend on the setup (either INTx or MSI).

Signed-off-by: Peter Xu 
---
 lib/pci-edu.h |  1 +
 lib/x86/intel-iommu.c | 94 +++
 lib/x86/intel-iommu.h |  1 +
 x86/intel-iommu.c | 44 +++-
 4 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/lib/pci-edu.h b/lib/pci-edu.h
index 8395ebe..9fe32c6 100644
--- a/lib/pci-edu.h
+++ b/lib/pci-edu.h
@@ -32,6 +32,7 @@
 #define EDU_REG_ALIVE   0x4
 #define EDU_REG_FACTORIAL   0x8
 #define EDU_REG_STATUS  0x20
+#define EDU_REG_INTR_RAISE  0x60
 #define EDU_REG_DMA_SRC 0x80
 #define EDU_REG_DMA_DST 0x88
 #define EDU_REG_DMA_COUNT   0x90
diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c
index 86b1805..20b9240 100644
--- a/lib/x86/intel-iommu.c
+++ b/lib/x86/intel-iommu.c
@@ -12,6 +12,7 @@
 
 #include "intel-iommu.h"
 #include "libcflat.h"
+#include "pci.h"
 
 /*
  * VT-d in QEMU currently only support 39 bits address width, which is
@@ -48,6 +49,26 @@ struct vtd_context_entry {
 } __attribute__ ((packed));
 typedef struct vtd_context_entry vtd_ce_t;
 
+struct vtd_irte {
+   uint32_t present:1;
+   uint32_t fault_disable:1;/* Fault Processing Disable */
+   uint32_t dest_mode:1;/* Destination Mode */
+   uint32_t redir_hint:1;   /* Redirection Hint */
+   uint32_t trigger_mode:1; /* Trigger Mode */
+   uint32_t delivery_mode:3;/* Delivery Mode */
+   uint32_t __avail:4;  /* Available spaces for software */
+   uint32_t __reserved_0:3; /* Reserved 0 */
+   uint32_t irte_mode:1;/* IRTE Mode */
+   uint32_t vector:8;   /* Interrupt Vector */
+   uint32_t __reserved_1:8; /* Reserved 1 */
+   uint32_t dest_id;/* Destination ID */
+   uint16_t source_id:16;   /* Source-ID */
+   uint64_t sid_q:2;/* Source-ID Qualifier */
+   uint64_t sid_vtype:2;/* Source-ID Validation Type */
+   uint64_t __reserved_2:44;/* Reserved 2 */
+} __attribute__ ((packed));
+typedef struct vtd_irte vtd_irte_t;
+
 #define VTD_RTA_MASK  (PAGE_MASK)
 #define VTD_IRTA_MASK (PAGE_MASK)
 
@@ -216,6 +237,79 @@ void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t 
pa, size_t size)
}
 }
 
+static uint16_t vtd_intr_index_alloc(void)
+{
+   static int index_ctr = 0;
+   assert(index_ctr < 65535);
+   return index_ctr++;
+}
+
+static void vtd_setup_irte(struct pci_dev *dev, vtd_irte_t *irte,
+  int vector, int dest_id)
+{
+   assert(sizeof(vtd_irte_t) == 16);
+   memset(irte, 0, sizeof(*irte));
+   irte->fault_disable = 1;
+   irte->dest_mode = 0; /* physical */
+   irte->trigger_mode = 0;  /* edge */
+   irte->delivery_mode = 0; /* fixed */
+   irte->irte_mode = 0; /* remapped */
+   irte->vector = vector;
+   irte->dest_id = dest_id;
+   irte->source_id = dev->bdf;
+   irte->sid_q = 0;
+   irte->sid_vtype = 1; /* full-sid verify */
+   irte->present = 1;
+}
+
+struct vtd_msi_addr {
+   uint32_t __dont_care:2;
+   uint32_t handle_15:1;/* handle[15] */
+   uint32_t shv:1;
+   uint32_t interrupt_format:1;
+   uint32_t handle_0_14:15; /* handle[0:14] */
+   uint32_t head:12;/* 0xfee */
+   uint32_t addr_hi;/* not used except with x2apic */
+} __attribute__ ((packed));
+typedef struct vtd_msi_addr vtd_msi_addr_t;
+
+struct vtd_msi_data {
+   uint16_t __reserved;
+   uint16_t subhandle;
+} __attribute__ ((packed));
+typedef struct vtd_msi_data vtd_msi_data_t;
+
+/**
+ * vtd_setup_msi - setup MSI message for a device
+ *
+ * @dev: PCI device to setup MSI
+ * @vector: interrupt vector
+ * @dest_id: destination processor
+ */
+bool vtd_setup_msi(struct pci_dev *dev, int vector, int dest_id)
+{
+   vtd_msi_data_t msi_data = {};
+   vtd_msi_addr_t msi_addr = {};
+   vtd_irte_t *irte = phys_to_virt(vtd_ir_table());
+   uint16_t index = vtd_intr_index_alloc();
+
+   assert(sizeof(vtd_msi_addr_t) == 8);
+   assert(sizeof(vtd_msi_data_t) == 4);
+
+   printf("INTR: setup IRTE index %d\n", index);
+   vtd_setup_irte(dev, irte + index, vector, dest_id);
+
+   msi_addr.handle_15 = index >> 15 & 1;
+   msi_addr.shv = 0;
+   msi_addr.interrupt_format = 1;
+   msi_addr.handle_0_14 = index & 0x7fff;
+   msi_addr.head = 0xfee;
+   msi_data.subhandle = 0;
+
+   return pci_setup_msi(dev, *(uint64_t *)&msi_addr,
+*(uint32_t

Re: [Qemu-devel] [PATCH for-2.9 0/3] cryptodev: prepare works for hotplug

2016-12-11 Thread Gonglei (Arei)
>
> From: Michael S. Tsirkin [mailto:m...@redhat.com]
> Sent: Sunday, December 11, 2016 11:38 AM
> To: Gonglei (Arei)
> Cc: qemu-devel@nongnu.org; Wubin (H); longpeng
> Subject: Re: [PATCH for-2.9 0/3] cryptodev: prepare works for hotplug
> 
> On Mon, Dec 05, 2016 at 11:27:09AM +0800, Gonglei wrote:
> > The patch set make the cryptodev object can be hot plugging
> > in safety, and which are preparing works for virtio-crypto
> > device hotpulgging.
> 
> 
> Thanks, pls remember to ping after 2.8 is out.
> 
OK, the v2 will be posted with virtio-crypto device hotplugging function.


Regards,
-Gonglei

> > Gonglei (3):
> >   cryptodev: introduce a new is_used property
> >   cryptodev: wrap the ready flag
> >   virtio-crypto: avoid one cryptodev device is used by multiple virtio
> > crypto devices
> >
> >  backends/cryptodev-builtin.c |  4 
> >  backends/cryptodev.c | 34
> ++
> >  hw/virtio/virtio-crypto.c| 22 +++---
> >  include/sysemu/cryptodev.h   | 42
> ++
> >  4 files changed, 95 insertions(+), 7 deletions(-)
> >
> > --
> > 1.8.3.1
> >



Re: [Qemu-devel] experience with SDL2, event loop & main thread

2016-12-11 Thread Fam Zheng
On Sat, 12/10 18:16, Liviu Ionescu wrote:
> conclusions:
> 
> - the graphical event loop and all graphical primitives must be called from 
> the main thread context
> - in qemu this is not possible directly; an inefficient but functional
> solution uses a timer programmed to call a function every few milliseconds, to
> poll the event loop. (if the qemu I/O event loop is executed on the main
> thread, the timer function will be called from the main thread context)

Isn't it possible to notify the main thread with an EventNotifier and process
the deferred events in its handler?

Fam

> - all graphical operations initiated by the all other thread (like the 
> emulator thread), must be deferred (in SDL using user events) to the 
> graphical event loop
> - a function to run graphical destruction must be registered with atexit()
> - only the main thread can call exit(), to ensure the destruction functions 
> are not called from other threads
> - exiting from other threads must be also deferred to the main thread, 
> possibly with unlocking a mutex.
> 
> 
> I hope that helps,
> 
> Liviu
> 
> 
> 
> 
> 
> 
> 



[Qemu-devel] [PATCHv3 3/5] pseries: Implement HPT resizing

2016-12-11 Thread David Gibson
This patch implements hypercalls allowing a PAPR guest to resize its own
hash page table.  This will eventually allow for more flexible memory
hotplug.

The implementation is partially asynchronous, handled in a special thread
running the hpt_prepare_thread() function.  The state of a pending resize
is stored in SPAPR_MACHINE->pending_hpt.

The H_RESIZE_HPT_PREPARE hypercall will kick off creation of a new HPT, or,
if one is already in progress, monitor it for completion.  If there is an
existing HPT resize in progress that doesn't match the size specified in
the call, it will cancel it, replacing it with a new one matching the
given size.

The H_RESIZE_HPT_COMMIT completes transition to a resized HPT, and can only
be called successfully once H_RESIZE_HPT_PREPARE has successfully
completed initialization of a new HPT.  The guest must ensure that there
are no concurrent accesses to the existing HPT while this is called (this
effectively means stop_machine() for Linux guests).

For now H_RESIZE_HPT_COMMIT goes through the whole old HPT, rehashing each
HPTE into the new HPT.  This can have quite high latency, but it seems to
be of the order of typical migration downtime latencies for HPTs of size
up to ~2GiB (which would be used in a 256GiB guest).

In future we probably want to move more of the rehashing to the "prepare"
phase, by having H_ENTER and other hcalls update both current and
pending HPTs.  That's a project for another day, but should be possible
without any changes to the guest interface.

Signed-off-by: David Gibson 
---
 hw/ppc/spapr.c  |   4 +-
 hw/ppc/spapr_hcall.c| 345 +++-
 include/hw/ppc/spapr.h  |   6 +
 target-ppc/mmu-hash64.h |   4 +
 4 files changed, 353 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 846ce51..d057031 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -93,8 +93,6 @@
 
 #define PHANDLE_XICP0x
 
-#define HTAB_SIZE(spapr)(1ULL << ((spapr)->htab_shift))
-
 static XICSState *try_create_xics(const char *type, int nr_servers,
   int nr_irqs, Error **errp)
 {
@@ -1055,7 +1053,7 @@ static void close_htab_fd(sPAPRMachineState *spapr)
 spapr->htab_fd = -1;
 }
 
-static int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
+int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
 {
 int shift;
 
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 72a9c4d..1e89061 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -2,6 +2,7 @@
 #include "qapi/error.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
+#include "qemu/error-report.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
 #include "helper_regs.h"
@@ -355,20 +356,319 @@ static target_ulong h_read(PowerPCCPU *cpu, 
sPAPRMachineState *spapr,
 return H_SUCCESS;
 }
 
+struct sPAPRPendingHPT {
+/* These fields are read-only after initialization */
+int shift;
+QemuThread thread;
+
+/* These fields are protected by the BQL */
+bool complete;
+
+/* These fields are private to the preparation thread if
+ * !complete, otherwise protected by the BQL */
+int ret;
+void *hpt;
+};
+
+static void free_pending_hpt(sPAPRPendingHPT *pending)
+{
+if (pending->hpt) {
+qemu_vfree(pending->hpt);
+}
+
+g_free(pending);
+}
+
+static void *hpt_prepare_thread(void *opaque)
+{
+sPAPRPendingHPT *pending = opaque;
+size_t size = 1ULL << pending->shift;
+
+pending->hpt = qemu_memalign(size, size);
+if (pending->hpt) {
+memset(pending->hpt, 0, size);
+pending->ret = H_SUCCESS;
+} else {
+pending->ret = H_NO_MEM;
+}
+
+qemu_mutex_lock_iothread();
+
+if (SPAPR_MACHINE(qdev_get_machine())->pending_hpt == pending) {
+/* Ready to go */
+pending->complete = true;
+} else {
+/* We've been cancelled, clean ourselves up */
+free_pending_hpt(pending);
+}
+
+qemu_mutex_unlock_iothread();
+return NULL;
+}
+
+/* Must be called with BQL held */
+static void cancel_hpt_prepare(sPAPRMachineState *spapr)
+{
+sPAPRPendingHPT *pending = spapr->pending_hpt;
+
+/* Let the thread know it's cancelled */
+spapr->pending_hpt = NULL;
+
+if (!pending) {
+/* Nothing to do */
+return;
+}
+
+if (!pending->complete) {
+/* thread will clean itself up */
+return;
+}
+
+free_pending_hpt(pending);
+}
+
+static int build_dimm_list(Object *obj, void *opaque)
+{
+GSList **list = opaque;
+
+if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+DeviceState *dev = DEVICE(obj);
+if (dev->realized) { /* only realized DIMMs matter */
+*list = g_slist_prepend(*list, dev);
+}
+}
+
+object_child_foreach(obj, build_dimm_list, opaque);
+return 0;
+}
+
+static ram_addr_t get_current_ram_size(void)
+{
+GSList *list = NULL, *item;
+ram_addr_t size = ram_size

[Qemu-devel] [PATCHv3 1/5] pseries: Add pseries-2.9 machine type

2016-12-11 Thread David Gibson
Signed-off-by: David Gibson 
Reviewed-by: Thomas Huth 
Reviewed-by: Laurent Vivier 
---
 hw/ppc/spapr.c  | 23 +--
 include/hw/compat.h |  3 +++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index cfadc46..0f25e83 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2761,18 +2761,37 @@ static const TypeInfo spapr_machine_info = {
 type_init(spapr_machine_register_##suffix)
 
 /*
+ * pseries-2.9
+ */
+static void spapr_machine_2_9_instance_options(MachineState *machine)
+{
+}
+
+static void spapr_machine_2_9_class_options(MachineClass *mc)
+{
+/* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(2_9, "2.9", true);
+
+/*
  * pseries-2.8
  */
+#define SPAPR_COMPAT_2_8\
+HW_COMPAT_2_8
+
 static void spapr_machine_2_8_instance_options(MachineState *machine)
 {
+spapr_machine_2_9_instance_options(machine);
 }
 
 static void spapr_machine_2_8_class_options(MachineClass *mc)
 {
-/* Defaults for the latest behaviour inherited from the base class */
+spapr_machine_2_9_class_options(mc);
+SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_8);
 }
 
-DEFINE_SPAPR_MACHINE(2_8, "2.8", true);
+DEFINE_SPAPR_MACHINE(2_8, "2.8", false);
 
 /*
  * pseries-2.7
diff --git a/include/hw/compat.h b/include/hw/compat.h
index 0f06e11..f8b8354 100644
--- a/include/hw/compat.h
+++ b/include/hw/compat.h
@@ -1,6 +1,9 @@
 #ifndef HW_COMPAT_H
 #define HW_COMPAT_H
 
+#define HW_COMPAT_2_8 \
+/* empty */
+
 #define HW_COMPAT_2_7 \
 {\
 .driver   = "virtio-pci",\
-- 
2.9.3




[Qemu-devel] [PATCHv3 2/5] pseries: Stubs for HPT resizing

2016-12-11 Thread David Gibson
This introduces stub implementations of the H_RESIZE_HPT_PREPARE and
H_RESIZE_HPT_COMMIT hypercalls which we hope to add in a PAPR
extension to allow run time resizing of a guest's hash page table.  It
also adds a new machine property for controlling whether this new
facility is available, and logic to check that against availability
with KVM (only supported with KVM PR for now).

Finally, it adds a new string to the hypertas property in the device
tree, advertising to the guest the availability of the HPT resizing
hypercalls.  This is a tentative suggested value, and would need to be
standardized by PAPR before being merged.

Signed-off-by: David Gibson 
---
 hw/ppc/spapr.c | 75 ++
 hw/ppc/spapr_hcall.c   | 36 
 hw/ppc/trace-events|  2 ++
 include/hw/ppc/spapr.h | 11 
 target-ppc/kvm.c   | 25 +
 target-ppc/kvm_ppc.h   |  5 
 6 files changed, 154 insertions(+)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 0f25e83..846ce51 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -760,6 +760,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void 
*fdt)
 if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
 add_str(hypertas, "hcall-multi-tce");
 }
+
+if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
+add_str(hypertas, "hcall-hpt-resize");
+}
+
 _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions",
  hypertas->str, hypertas->len));
 g_string_free(hypertas, TRUE);
@@ -1839,11 +1844,40 @@ static void ppc_spapr_init(MachineState *machine)
 long load_limit, fw_size;
 char *filename;
 int smt = kvmppc_smt_threads();
+Error *resize_hpt_err = NULL;
 
 msi_nonbroken = true;
 
 QLIST_INIT(&spapr->phbs);
 
+/* Check HPT resizing availability */
+kvmppc_check_papr_resize_hpt(&resize_hpt_err);
+if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) {
+/*
+ * If the user explicitly requested a mode we should either
+ * supply it, or fail completely (which we do below).  But if
+ * it's not set explicitly, we reset our mode to something
+ * that works
+ */
+if (resize_hpt_err) {
+spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
+error_free(resize_hpt_err);
+resize_hpt_err = NULL;
+} else {
+spapr->resize_hpt = smc->resize_hpt_default;
+}
+}
+
+assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT);
+
+if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) {
+/*
+ * User requested HPT resize, but this host can't supply it.  Bail out
+ */
+error_report_err(resize_hpt_err);
+exit(1);
+}
+
 /* Allocate RMA if necessary */
 rma_alloc_size = kvmppc_alloc_rma(&rma);
 
@@ -2236,6 +2270,40 @@ static void spapr_set_modern_hotplug_events(Object *obj, 
bool value,
 spapr->use_hotplug_event_source = value;
 }
 
+static char *spapr_get_resize_hpt(Object *obj, Error **errp)
+{
+sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+switch (spapr->resize_hpt) {
+case SPAPR_RESIZE_HPT_DEFAULT:
+return g_strdup("default");
+case SPAPR_RESIZE_HPT_DISABLED:
+return g_strdup("disabled");
+case SPAPR_RESIZE_HPT_ENABLED:
+return g_strdup("enabled");
+case SPAPR_RESIZE_HPT_REQUIRED:
+return g_strdup("required");
+}
+assert(0);
+}
+
+static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp)
+{
+sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+if (strcmp(value, "default") == 0) {
+spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT;
+} else if (strcmp(value, "disabled") == 0) {
+spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED;
+} else if (strcmp(value, "enabled") == 0) {
+spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED;
+} else if (strcmp(value, "required") == 0) {
+spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED;
+} else {
+error_setg(errp, "Bad value for \"resize-hpt\" property");
+}
+}
+
 static void spapr_machine_initfn(Object *obj)
 {
 sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
@@ -2256,6 +2324,12 @@ static void spapr_machine_initfn(Object *obj)
 " place of standard EPOW events when 
possible"
 " (required for memory hot-unplug 
support)",
 NULL);
+
+object_property_add_str(obj, "resize-hpt",
+spapr_get_resize_hpt, spapr_set_resize_hpt, NULL);
+object_property_set_description(obj, "resize-hpt",
+"Resizing of the Hash Page Table (enabled, 
disabled, required)",
+NULL);
 }
 
 static void spapr_machine_finalizefn(Object *obj)
@@ -2707,6 +2781,7 @@ static void spapr_machine_class_i

[Qemu-devel] [PATCHv3 5/5] pseries: Use smaller default hash page tables when guest can resize

2016-12-11 Thread David Gibson
We've now implemented a PAPR extension allowing PAPR guest to resize
their hash page table (HPT) during runtime.

This patch makes use of that facility to allocate smaller HPTs by default.
Specifically when a guest is aware of the HPT resize facility, qemu sizes
the HPT to the initial memory size, rather than the maximum memory size on
the assumption that the guest will resize its HPT if necessary for hot
plugged memory.

When the initial memory size is much smaller than the maximum memory size
(a common configuration with e.g. oVirt / RHEV) then this can save
significant memory on the HPT.

If the guest does *not* advertise HPT resize awareness when it makes the
ibm,client-architecture-support call, qemu resizes the HPT for maxmimum
memory size (unless it's been configured not to allow such guests at all).

For now we make that reallocation assuming the guest has not yet used the
HPT at all.  That's true in practice, but not, strictly, an architectural
or PAPR requirement.  If we need to in future we can fix this by having
the client-architecture-support call reboot the guest with the revised
HPT size (the client-architecture-support call is explicitly permitted to
trigger a reboot in this way).

Signed-off-by: David Gibson 
---
 hw/ppc/spapr.c  | 21 -
 hw/ppc/spapr_hcall.c| 32 
 include/hw/ppc/spapr.h  |  2 ++
 include/hw/ppc/spapr_ovec.h |  1 +
 4 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index f05d0e5..51b189d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1066,8 +1066,8 @@ int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
 return shift;
 }
 
-static void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
- Error **errp)
+void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
+  Error **errp)
 {
 long rc;
 
@@ -1140,14 +1140,20 @@ static void ppc_spapr_reset(void)
 hwaddr rtas_addr, fdt_addr;
 void *fdt;
 int rc;
+int hpt_shift;
 
 /* Check for unknown sysbus devices */
 foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);
 
 /* Allocate and/or reset the hash page table */
-spapr_reallocate_hpt(spapr,
- spapr_hpt_shift_for_ramsize(machine->maxram_size),
- &error_fatal);
+if ((spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED)
+|| (spapr->cas_reboot
+&& !spapr_ovec_test(spapr->ov5_cas, OV5_HPT_RESIZE))) {
+hpt_shift = spapr_hpt_shift_for_ramsize(machine->maxram_size);
+} else {
+hpt_shift = spapr_hpt_shift_for_ramsize(machine->ram_size);
+}
+spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal);
 
 /* Update the RMA size if necessary */
 if (spapr->vrma_adjust) {
@@ -1941,6 +1947,11 @@ static void ppc_spapr_init(MachineState *machine)
 spapr_ovec_set(spapr->ov5, OV5_HP_EVT);
 }
 
+/* advertise support for HPT resizing */
+if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) {
+spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE);
+}
+
 /* init CPUs */
 if (machine->cpu_model == NULL) {
 machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu;
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 1e89061..5bebfc3 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1415,6 +1415,38 @@ static target_ulong 
h_client_architecture_support(PowerPCCPU *cpu_,
 
 ov5_guest = spapr_ovec_parse_vector(ov_table, 5);
 
+/*
+ * HPT resizing is a bit of a special case, because when enabled
+ * we assume the guest will support it until it says it doesn't,
+ * instead of assuming it won't support it until it says it does.
+ * Strictly speaking that approach could break for guests which
+ * don't make a CAS call, but those are so old we don't care about
+ * them.  Without that assumption we'd have to make at least a
+ * temporary allocation of an HPT sized for max memory, which
+ * could be impossibly difficult under KVM HV if maxram is large.
+ */
+if (!spapr_ovec_test(ov5_guest, OV5_HPT_RESIZE)) {
+int maxshift = 
spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size);
+
+if (spapr->resize_hpt == SPAPR_RESIZE_HPT_REQUIRED) {
+error_report(
+"h_client_architecture_support: Guest doesn't support HPT 
resizing, but resize-hpt=required");
+exit(1);
+}
+
+if (spapr->htab_shift < maxshift) {
+CPUState *cs;
+/* Guest doesn't know about HPT resizing, so we
+ * pre-emptively resize for the maximum permitted RAM.  At
+ * the point this is called, nothing should have been
+ * entered into the existing HPT */
+spapr_reallocate_hpt(spapr, maxshift, &error_fatal);
+CPU_FOREACH(cs) {
+run_on_cpu(

[Qemu-devel] [PATCHv3 0/5] Hash Page Table resizing for TCG pseries guests

2016-12-11 Thread David Gibson
This series implements the host side of the PAPR ACR to allow runtime
resizing of the Hashed Page Table (HPT) for pseries guests.
Exercising this feature requires a guest OS which is also aware of it.
Patches to implement the guest side in Linux have just been submitted
upstream:

https://lists.ozlabs.org/pipermail/linuxppc-dev/2016-December/152164.html

Availability of the feature is controlled by a new 'resize-hpt'
machine option: it can be set to "disabled", "enabled" or "required".
The last means that qemu will refuse to boot a guest which is not
aware of the HPT resizing feature (it will instead quit during feature
negotiation).  This is potentially useful because guests which don't
support resizing will need an HPT sized for their maximum possible
RAM, which can be very wasteful of host resources.

So far this is only tested for TCG guests.  PR KVM guests should work
in theory, but I haven't been able to test yet due to (probably
unrelated) problems booting a suitable guest kernel.  HV KVM guests
will require substantial extra work in the host kernel; development is
in progress.

Changes since v2:
 * Some clearer comments based on review
 * Some minor cleanups based on review 

David Gibson (5):
  pseries: Add pseries-2.9 machine type
  pseries: Stubs for HPT resizing
  pseries: Implement HPT resizing
  pseries: Enable HPT resizing for 2.9
  pseries: Use smaller default hash page tables when guest can resize

 hw/ppc/spapr.c  | 126 --
 hw/ppc/spapr_hcall.c| 407 
 hw/ppc/trace-events |   2 +
 include/hw/compat.h |   3 +
 include/hw/ppc/spapr.h  |  19 +++
 include/hw/ppc/spapr_ovec.h |   1 +
 target-ppc/kvm.c|  25 +++
 target-ppc/kvm_ppc.h|   5 +
 target-ppc/mmu-hash64.h |   4 +
 9 files changed, 582 insertions(+), 10 deletions(-)

-- 
2.9.3




Re: [Qemu-devel] [Qemu-ppc] [PATCH v2 5/6] target-ppc: implement xxextractuw instruction

2016-12-11 Thread David Gibson
On Mon, Dec 12, 2016 at 09:31:11AM +0530, Nikunj Dadhania wrote:
> On 12 December 2016 at 06:00, David Gibson  
> wrote:
> > On Fri, Dec 09, 2016 at 05:47:24PM +0530, Nikunj A Dadhania wrote:
> >> xxextractuw: VSX Vector Extract Unsigned Word
> >>
> >> Signed-off-by: Nikunj A Dadhania 
> >> ---
> >>  target-ppc/helper.h |  1 +
> >>  target-ppc/int_helper.c | 21 +
> >>  target-ppc/translate/vsx-impl.inc.c | 27 +++
> >>  target-ppc/translate/vsx-ops.inc.c  |  5 +
> >>  4 files changed, 54 insertions(+)
> >>
> >> diff --git a/target-ppc/helper.h b/target-ppc/helper.h
> >> index 4707db4..8b30420 100644
> >> --- a/target-ppc/helper.h
> >> +++ b/target-ppc/helper.h
> >> @@ -540,6 +540,7 @@ DEF_HELPER_2(xvrspip, void, env, i32)
> >>  DEF_HELPER_2(xvrspiz, void, env, i32)
> >>  DEF_HELPER_2(xxperm, void, env, i32)
> >>  DEF_HELPER_2(xxpermr, void, env, i32)
> >> +DEF_HELPER_4(xxextractuw, void, env, tl, tl, i32)
> >>
> >>  DEF_HELPER_2(efscfsi, i32, env, i32)
> >>  DEF_HELPER_2(efscfui, i32, env, i32)
> >> diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
> >> index 7989b1f..e3f66ac 100644
> >> --- a/target-ppc/int_helper.c
> >> +++ b/target-ppc/int_helper.c
> >> @@ -2033,6 +2033,27 @@ VEXTRACT(uw, u32)
> >>  VEXTRACT(d, u64)
> >>  #undef VEXTRACT
> >>
> >> +void helper_xxextractuw(CPUPPCState *env, target_ulong xtn,
> >> +target_ulong xbn, uint32_t index)
> >> +{
> >> +ppc_vsr_t xt, xb;
> >> +size_t es = sizeof(uint32_t);
> >> +uint32_t ext_index;
> >> +
> >> +getVSR(xbn, &xb, env);
> >> +memset(&xt, 0, sizeof(xt));
> >> +
> >> +#if defined(HOST_WORDS_BIGENDIAN)
> >> +ext_index = index;
> >> +memcpy(&xt.u8[8 - es], &xb.u8[ext_index], es);
> >> +#else
> >> +ext_index = (16 - index) - es;
> >> +memcpy(&xt.u8[8], &xb.u8[ext_index], es);
> >
> > Hm.  So, IIUC, ext_index is the byte element - in IBM numbering - to
> > start copying from.  But I thought that when we have an LE host, the
> > IBM byte element ordering is reversed from the actual order in host
> > memory, so we'd need &xb.u8[16 - ext_index - es]
> 
> I am not getting you, I am getting index from user. So in case of BE host:
> 
> ext_index = index;
> 
> LE Host:
> 
> ext_index = (16 - index) - es;
> 
> I am already doing that. Am I missing something.

Duh, sorry, apparently I'm blind and missed that logic.

> >> +#endif
> >> +
> >> +putVSR(xtn, &xt, env);
> >> +}
> >> +
> >>  #define VEXT_SIGNED(name, element, mask, cast, recast)  \
> >>  void helper_##name(ppc_avr_t *r, ppc_avr_t *b)  \
> >>  {   \
> >> diff --git a/target-ppc/translate/vsx-impl.inc.c 
> >> b/target-ppc/translate/vsx-impl.inc.c
> >> index 2a17c35..1c40a35 100644
> >> --- a/target-ppc/translate/vsx-impl.inc.c
> >> +++ b/target-ppc/translate/vsx-impl.inc.c
> >> @@ -1180,6 +1180,33 @@ static void gen_xxsldwi(DisasContext *ctx)
> >>  tcg_temp_free_i64(xtl);
> >>  }
> >>
> >> +#define VSX_EXTRACT(name)   \
> >> +static void gen_##name(DisasContext *ctx)   \
> >> +{   \
> >> +TCGv xt, xb;\
> >> +TCGv_i32 t0 = tcg_temp_new_i32();   \
> >> +uint8_t uimm = UIMM4(ctx->opcode);  \
> >> +\
> >> +if (unlikely(!ctx->vsx_enabled)) {  \
> >> +gen_exception(ctx, POWERPC_EXCP_VSXU);  \
> >> +return; \
> >> +}   \
> >> +if (uimm > 12) {\
> >
> > Throughout the helper you use es == sizeof(uint32_t), but here you
> > hardcode the assumption of 4 bytes, seems a bit inconsistent.
> >
> >> +tcg_gen_movi_i64(cpu_vsrh(xT(ctx->opcode)), 0); \
> >> +tcg_gen_movi_i64(cpu_vsrl(xT(ctx->opcode)), 0); \
> >> +return; \
> >
> > So, I know the architecture says it is undefined.  But since you're
> > testing for the bogus case anyway, why not turn this into an
> > exception. That seems like it would be more helpful for debugging the
> > guest than just setting the result to zero.  Or is this done to match
> > actual hardware behaviour?
> 
> I havent had a change to run on the real hardware, but on the system
> simulator, it happily
> returns extracted content even if UIMM > 12.

Hm.  Returns what exactly?

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way

[Qemu-devel] [PATCHv3 4/5] pseries: Enable HPT resizing for 2.9

2016-12-11 Thread David Gibson
We've now implemented a PAPR extensions which allows PAPR guests (i.e.
"pseries" machine type) to resize their hash page table during runtime.

However, that extension is only enabled if explicitly chosen on the
command line.  This patch enables it by default for spapr-2.9, but leaves
it disabled (by default) for older machine types.

Signed-off-by: David Gibson 
Reviewed-by: Laurent Vivier 
---
 hw/ppc/spapr.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d057031..f05d0e5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2779,7 +2779,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 
 smc->dr_lmb_enabled = true;
 smc->tcg_default_cpu = "POWER8";
-smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED;
+smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
 mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus;
 fwc->get_dev_path = spapr_get_fw_dev_path;
 nc->nmi_monitor_handler = spapr_nmi;
@@ -2860,8 +2860,11 @@ static void 
spapr_machine_2_8_instance_options(MachineState *machine)
 
 static void spapr_machine_2_8_class_options(MachineClass *mc)
 {
+sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+
 spapr_machine_2_9_class_options(mc);
 SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_8);
+smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED;
 }
 
 DEFINE_SPAPR_MACHINE(2_8, "2.8", false);
-- 
2.9.3




Re: [Qemu-devel] Reproducible crash on PCIe hotplug

2016-12-11 Thread Cao jin


On 12/10/2016 04:39 AM, Eduardo Habkost wrote:
> Using latest qemu.git master:
> 
>   $ qemu-system-x86_64 -machine q35 -readconfig docs/q35-chipset.cfg -monitor 
> stdio
>   QEMU 2.7.93 monitor - type 'help' for more information
>   (qemu) device_add e1000e,bus=ich9-pcie-port-4,addr=00
>   (qemu) device_add e1000e,bus=ich9-pcie-port-4,addr=08
>   Segmentation fault (core dumped)
> 
> It crashes at:
> 
>   #7  0x5598d7dc in do_pci_register_device (errp=0x7fffbfd0, 
> devfn=64, name=0x565df340 "e1000e", bus=0x58487380, 
> pci_dev=0x589cd000)
>   at /home/ehabkost/rh/proj/virt/qemu/hw/pci/pci.c:983
>   983 error_setg(errp, "PCI: slot %d function 0 already ocuppied 
> by %s,"
>   (gdb) l
>   978PCI_SLOT(devfn), PCI_FUNC(devfn), name,
>   979bus->devices[devfn]->name);
>   980 return NULL;
>   981 } else if (dev->hotplugged &&
>   982pci_get_function_0(pci_dev)) {
>   983 error_setg(errp, "PCI: slot %d function 0 already ocuppied 
> by %s,"
>   984" new func %s cannot be exposed to guest.",
>   985PCI_SLOT(devfn),
>   986bus->devices[PCI_DEVFN(PCI_SLOT(devfn), 
> 0)]->name,
>   987name);
> 

Thanks for informing me. I am kind of busy for now, so I suppose I will
investigate it after 2.8 release.
-- 
Sincerely,
Cao jin





Re: [Qemu-devel] [PATCH v6 2/2] crypto: add virtio-crypto driver

2016-12-11 Thread Gonglei (Arei)
Hi, Michael & Herbert

Because the virtio-crypto device emulation had been in QEMU 2.8,
would you please merge the virtio-crypto driver for 4.10 if no other
comments? If so, Miachel pls ack and/or review the patch, then
Herbert will take it (I asked him last week). Thank you!

Ps: Note on 4.10 merge window timing from Linus
 https://lkml.org/lkml/2016/12/7/506

Dec 23rd is the deadline for 4.10 merge window.

Regards,
-Gonglei


> -Original Message-
> From: Gonglei (Arei)
> Sent: Thursday, December 08, 2016 12:37 PM
> Subject: [PATCH v6 2/2] crypto: add virtio-crypto driver
> 
> This patch introduces virtio-crypto driver for Linux Kernel.
> 
> The virtio crypto device is a virtual cryptography device
> as well as a kind of virtual hardware accelerator for
> virtual machines. The encryption anddecryption requests
> are placed in the data queue and are ultimately handled by
> thebackend crypto accelerators. The second queue is the
> control queue used to create or destroy sessions for
> symmetric algorithms and will control some advanced features
> in the future. The virtio crypto device provides the following
> cryptoservices: CIPHER, MAC, HASH, and AEAD.
> 
> For more information about virtio-crypto device, please see:
>   http://qemu-project.org/Features/VirtioCrypto
> 
> CC: Michael S. Tsirkin 
> CC: Cornelia Huck 
> CC: Stefan Hajnoczi 
> CC: Herbert Xu 
> CC: Halil Pasic 
> CC: David S. Miller 
> CC: Zeng Xin 
> Signed-off-by: Gonglei 
> ---
>  MAINTAINERS  |   9 +
>  drivers/crypto/Kconfig   |   2 +
>  drivers/crypto/Makefile  |   1 +
>  drivers/crypto/virtio/Kconfig|  10 +
>  drivers/crypto/virtio/Makefile   |   5 +
>  drivers/crypto/virtio/virtio_crypto_algs.c   | 541
> +++
>  drivers/crypto/virtio/virtio_crypto_common.h | 122 ++
>  drivers/crypto/virtio/virtio_crypto_core.c   | 464
> +++
>  drivers/crypto/virtio/virtio_crypto_mgr.c| 264 +
>  include/uapi/linux/Kbuild|   1 +
>  include/uapi/linux/virtio_crypto.h   | 450
> ++
>  include/uapi/linux/virtio_ids.h  |   1 +
>  12 files changed, 1870 insertions(+)
>  create mode 100644 drivers/crypto/virtio/Kconfig
>  create mode 100644 drivers/crypto/virtio/Makefile
>  create mode 100644 drivers/crypto/virtio/virtio_crypto_algs.c
>  create mode 100644 drivers/crypto/virtio/virtio_crypto_common.h
>  create mode 100644 drivers/crypto/virtio/virtio_crypto_core.c
>  create mode 100644 drivers/crypto/virtio/virtio_crypto_mgr.c
>  create mode 100644 include/uapi/linux/virtio_crypto.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ad9b965..cccaaf0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12810,6 +12810,7 @@ F:drivers/net/virtio_net.c
>  F:   drivers/block/virtio_blk.c
>  F:   include/linux/virtio_*.h
>  F:   include/uapi/linux/virtio_*.h
> +F:   drivers/crypto/virtio/
> 
>  VIRTIO DRIVERS FOR S390
>  M:   Christian Borntraeger 
> @@ -12846,6 +12847,14 @@ S:   Maintained
>  F:   drivers/virtio/virtio_input.c
>  F:   include/uapi/linux/virtio_input.h
> 
> +VIRTIO CRYPTO DRIVER
> +M:  Gonglei 
> +L:  virtualizat...@lists.linux-foundation.org
> +L:  linux-cry...@vger.kernel.org
> +S:  Maintained
> +F:  drivers/crypto/virtio/
> +F:  include/uapi/linux/virtio_crypto.h
> +
>  VIA RHINE NETWORK DRIVER
>  S:   Orphan
>  F:   drivers/net/ethernet/via/via-rhine.c
> diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
> index 4d2b81f..7956478 100644
> --- a/drivers/crypto/Kconfig
> +++ b/drivers/crypto/Kconfig
> @@ -555,4 +555,6 @@ config CRYPTO_DEV_ROCKCHIP
> 
>  source "drivers/crypto/chelsio/Kconfig"
> 
> +source "drivers/crypto/virtio/Kconfig"
> +
>  endif # CRYPTO_HW
> diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
> index ad7250f..bc53cb8 100644
> --- a/drivers/crypto/Makefile
> +++ b/drivers/crypto/Makefile
> @@ -32,3 +32,4 @@ obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/
>  obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/
>  obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/
>  obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/
> +obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio/
> diff --git a/drivers/crypto/virtio/Kconfig b/drivers/crypto/virtio/Kconfig
> new file mode 100644
> index 000..d80f733
> --- /dev/null
> +++ b/drivers/crypto/virtio/Kconfig
> @@ -0,0 +1,10 @@
> +config CRYPTO_DEV_VIRTIO
> + tristate "VirtIO crypto driver"
> + depends on VIRTIO
> + select CRYPTO_AEAD
> + select CRYPTO_AUTHENC
> + select CRYPTO_BLKCIPHER
> + default m
> + help
> +   This driver provides support for virtio crypto device. If you
> +   choose 'M' here, this module will be called virtio_crypto.
> diff --git a/drivers/crypto/virtio/Makefile b/drivers/crypto/virtio/Makefile
> new file mode 100644
> index 000..dd342c9
> --- /dev/null
> +++ b/drivers/crypto/virtio/Makefile
> @@ -0,0 +1,5 @@
> +

Re: [Qemu-devel] experience with SDL2, event loop & main thread

2016-12-11 Thread Liviu Ionescu

> On 12 Dec 2016, at 05:35, Fam Zheng  wrote:
> 
> Isn't it possible to notify the main thread with an EventNotifier and process
> the deferred events in its handler?

ideally, the SDL main loop might be re-implemented asynchronously, for example 
using a pipe to pass the events, and in this case the SDL would be just a 
regular client of the main I/O loop.

any idea how difficult would be to push any changes to SDL?


regards,

Liviu




[Qemu-devel] [PATCH for-2.9 v1 1/7] qapi: crypto: add defination about HMAC algorithms

2016-12-11 Thread Longpeng(Mike)
This patch introduce HMAC algorithms relevant defination, they will
be used by the following patch.

Signed-off-by: Longpeng(Mike) 
---
 qapi/crypto.json | 17 +
 1 file changed, 17 insertions(+)

diff --git a/qapi/crypto.json b/qapi/crypto.json
index f4fd93b..e63862a 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -55,6 +55,23 @@
 
 
 ##
+# @QCryptoHmacAlgorithm:
+#
+# The supported algorithms for hash-based message authentication code
+#
+# @md5: HMAC-MD5
+# @sha1: HMAC-SHA1
+# @sha256: HMAC-SHA256
+# @sha512: HMAC-SHA512
+#
+# Since 2.9
+##
+{ 'enum': 'QCryptoHmacAlgorithm',
+  'prefix': 'QCRYPTO_HMAC_ALG',
+  'data': ['md5', 'sha1', 'sha256', 'sha512']}
+
+
+##
 # @QCryptoCipherAlgorithm:
 #
 # The supported algorithms for content encryption ciphers
-- 
1.8.3.1





[Qemu-devel] [PATCH for-2.9 v1 2/7] crypto: add HMAC algorithms framework

2016-12-11 Thread Longpeng(Mike)
This patch introduce HMAC algorithms framework.

Signed-off-by: Longpeng(Mike) 
---
 crypto/Makefile.objs |   4 ++
 crypto/hmac-gcrypt.c |  44 ++
 crypto/hmac-glib.c   |  44 ++
 crypto/hmac-nettle.c |  44 ++
 crypto/hmac.c|  72 ++
 crypto/hmac.h| 166 +++
 6 files changed, 374 insertions(+)
 create mode 100644 crypto/hmac-gcrypt.c
 create mode 100644 crypto/hmac-glib.c
 create mode 100644 crypto/hmac-nettle.c
 create mode 100644 crypto/hmac.c
 create mode 100644 crypto/hmac.h

diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index a36d2d9..7978a46 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -3,6 +3,10 @@ crypto-obj-y += hash.o
 crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o
 crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o
 crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hash-glib.o
+crypto-obj-y += hmac.o
+crypto-obj-$(CONFIG_NETTLE) += hmac-nettle.o
+crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hmac-gcrypt.o
+crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hmac-glib.o
 crypto-obj-y += aes.o
 crypto-obj-y += desrfb.o
 crypto-obj-y += cipher.o
diff --git a/crypto/hmac-gcrypt.c b/crypto/hmac-gcrypt.c
new file mode 100644
index 000..26f42bc
--- /dev/null
+++ b/crypto/hmac-gcrypt.c
@@ -0,0 +1,44 @@
+/*
+ * QEMU Crypto hmac algorithms (based on libgcrypt)
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ *Longpeng(Mike) 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/hmac.h"
+
+bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg)
+{
+return false;
+}
+
+QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg,
+  const uint8_t *key, size_t nkey,
+  Error **errp)
+{
+return NULL;
+}
+
+void qcrypto_hmac_free(QCryptoHmac *hmac)
+{
+return;
+}
+
+int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
+const struct iovec *iov,
+size_t niov,
+uint8_t **result,
+size_t *resultlen,
+Error **errp)
+{
+return -1;
+}
diff --git a/crypto/hmac-glib.c b/crypto/hmac-glib.c
new file mode 100644
index 000..42f63c6
--- /dev/null
+++ b/crypto/hmac-glib.c
@@ -0,0 +1,44 @@
+/*
+ * QEMU Crypto hmac algorithms (based on glib)
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ *Longpeng(Mike) 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/hmac.h"
+
+bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg)
+{
+return false;
+}
+
+QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg,
+  const uint8_t *key, size_t nkey,
+  Error **errp)
+{
+return NULL;
+}
+
+void qcrypto_hmac_free(QCryptoHmac *hmac)
+{
+return;
+}
+
+int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
+const struct iovec *iov,
+size_t niov,
+uint8_t **result,
+size_t *resultlen,
+Error **errp)
+{
+return -1;
+}
diff --git a/crypto/hmac-nettle.c b/crypto/hmac-nettle.c
new file mode 100644
index 000..7a9cd2e
--- /dev/null
+++ b/crypto/hmac-nettle.c
@@ -0,0 +1,44 @@
+/*
+ * QEMU Crypto hmac algorithms (based on nettle)
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ *Longpeng(Mike) 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/hmac.h"
+
+bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg)
+{
+return false;
+}
+
+QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg,
+  const uint8_t *key, size_t nkey,
+  Error **errp)
+{
+return NULL;
+}
+
+void qcrypto_hmac_free(QCryptoHmac *hmac)
+{
+return;
+}
+
+int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
+const struct iovec *iov,
+size_t niov,
+uint8_t **result,
+size_t *resultlen,
+Error **errp)
+{
+return -1;
+}
diff --git a/crypto/hmac.c b/crypto/hmac.c
new file mode 100644
index 000..5750405
--- /dev/null
+++ b/crypto/hmac.c
@@ -0,0 +1,72 @@
+/*
+ * QEMU C

[Qemu-devel] [PATCH for-2.9 v1 4/7] crypto: support HMAC algorithms based on libgcrypt

2016-12-11 Thread Longpeng(Mike)
This patch add HMAC algorithms based on libgcrypt support

Signed-off-by: Longpeng(Mike) 
---
 crypto/hmac-gcrypt.c | 138 +++
 1 file changed, 138 insertions(+)

diff --git a/crypto/hmac-gcrypt.c b/crypto/hmac-gcrypt.c
index 26f42bc..6cf3046 100644
--- a/crypto/hmac-gcrypt.c
+++ b/crypto/hmac-gcrypt.c
@@ -15,6 +15,142 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "crypto/hmac.h"
+#include 
+
+#ifdef CONFIG_GCRYPT_SUPPORT_HMAC
+
+static int qcrypto_hmac_alg_map[QCRYPTO_HMAC_ALG__MAX] = {
+[QCRYPTO_HMAC_ALG_MD5] = GCRY_MAC_HMAC_MD5,
+[QCRYPTO_HMAC_ALG_SHA1] = GCRY_MAC_HMAC_SHA1,
+[QCRYPTO_HMAC_ALG_SHA256] = GCRY_MAC_HMAC_SHA256,
+[QCRYPTO_HMAC_ALG_SHA512] = GCRY_MAC_HMAC_SHA512,
+};
+
+typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt;
+struct QCryptoHmacGcrypt {
+gcry_mac_hd_t handle;
+};
+
+bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg)
+{
+if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
+qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) {
+return true;
+}
+
+return false;
+}
+
+QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg,
+  const uint8_t *key, size_t nkey,
+  Error **errp)
+{
+QCryptoHmac *hmac;
+QCryptoHmacGcrypt *ctx;
+gcry_error_t err;
+
+if (!qcrypto_hmac_supports(alg)) {
+error_setg(errp, "Unsupported hmac algorithm %s",
+QCryptoHmacAlgorithm_lookup[alg]);
+return NULL;
+}
+
+hmac = g_new0(QCryptoHmac, 1);
+hmac->alg = alg;
+
+ctx = g_new0(QCryptoHmacGcrypt, 1);
+
+err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg],
+GCRY_MAC_FLAG_SECURE, NULL);
+if (err != 0) {
+error_setg(errp, "Cannot initialize hmac: %s",
+gcry_strerror(err));
+goto error;
+}
+
+err = gcry_mac_setkey(ctx->handle, (const void *)key, nkey);
+if (err != 0) {
+error_setg(errp, "Cannot set key: %s",
+gcry_strerror(err));
+goto error;
+}
+
+hmac->opaque = ctx;
+return hmac;
+
+error:
+g_free(ctx);
+g_free(hmac);
+return NULL;
+}
+
+void qcrypto_hmac_free(QCryptoHmac *hmac)
+{
+QCryptoHmacGcrypt *ctx;
+
+if (!hmac) {
+return;
+}
+
+ctx = hmac->opaque;
+gcry_mac_close(ctx->handle);
+
+g_free(ctx);
+g_free(hmac);
+}
+
+int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
+const struct iovec *iov,
+size_t niov,
+uint8_t **result,
+size_t *resultlen,
+Error **errp)
+{
+QCryptoHmacGcrypt *ctx;
+gcry_error_t err;
+uint32_t ret;
+int i;
+
+ctx = hmac->opaque;
+
+for (i = 0; i < niov; i++) {
+gcry_mac_write(ctx->handle, iov[i].iov_base, iov[i].iov_len);
+}
+
+ret = gcry_mac_get_algo_maclen(qcrypto_hmac_alg_map[hmac->alg]);
+if (ret <= 0) {
+error_setg(errp, "Unable to get hmac length: %s",
+gcry_strerror(ret));
+return -1;
+}
+
+if (*resultlen == 0) {
+*resultlen = ret;
+*result = g_new0(uint8_t, *resultlen);
+} else if (*resultlen != ret) {
+error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
+*resultlen, ret);
+return -1;
+}
+
+err = gcry_mac_read(ctx->handle, *result, resultlen);
+if (err != 0) {
+error_setg(errp, "Cannot get result: %s",
+gcry_strerror(err));
+return -1;
+}
+
+err = gcry_mac_reset(ctx->handle);
+if (err != 0) {
+error_setg(errp, "Cannot reset hmac context: %s",
+gcry_strerror(err));
+return -1;
+}
+
+return 0;
+}
+
+#else
 
 bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg)
 {
@@ -42,3 +178,5 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
 {
 return -1;
 }
+
+#endif
-- 
1.8.3.1





[Qemu-devel] [PATCH for-2.9 v1 6/7] crypto: support HMAC algorithms based on nettle

2016-12-11 Thread Longpeng(Mike)
This patch add nettle-backed HMAC algorithms support

Signed-off-by: Longpeng(Mike) 
---
 crypto/hmac-nettle.c | 118 +--
 1 file changed, 115 insertions(+), 3 deletions(-)

diff --git a/crypto/hmac-nettle.c b/crypto/hmac-nettle.c
index 7a9cd2e..a082bc0 100644
--- a/crypto/hmac-nettle.c
+++ b/crypto/hmac-nettle.c
@@ -15,9 +15,66 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "crypto/hmac.h"
+#include 
+
+typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx,
+size_t key_length, const uint8_t *key);
+
+typedef void (*qcrypto_nettle_hmac_update)(void *ctx,
+size_t length, const uint8_t *data);
+
+typedef void (*qcrypto_nettle_hmac_digest)(void *ctx,
+size_t length, uint8_t *digest);
+
+typedef struct QCryptoHmacNettle QCryptoHmacNettle;
+struct QCryptoHmacNettle {
+union qcrypto_nettle_hmac_ctx {
+struct hmac_md5_ctx md5_ctx;
+struct hmac_sha1_ctx sha1_ctx;
+struct hmac_sha256_ctx sha256_ctx;
+struct hmac_sha512_ctx sha512_ctx;
+} u;
+};
+
+struct qcrypto_nettle_hmac_alg {
+qcrypto_nettle_hmac_setkey setkey;
+qcrypto_nettle_hmac_update update;
+qcrypto_nettle_hmac_digest digest;
+size_t len;
+} qcrypto_hmac_alg_map[QCRYPTO_HMAC_ALG__MAX] = {
+[QCRYPTO_HMAC_ALG_MD5] = {
+.setkey = (qcrypto_nettle_hmac_setkey)hmac_md5_set_key,
+.update = (qcrypto_nettle_hmac_update)hmac_md5_update,
+.digest = (qcrypto_nettle_hmac_digest)hmac_md5_digest,
+.len = MD5_DIGEST_SIZE,
+},
+[QCRYPTO_HMAC_ALG_SHA1] = {
+.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha1_set_key,
+.update = (qcrypto_nettle_hmac_update)hmac_sha1_update,
+.digest = (qcrypto_nettle_hmac_digest)hmac_sha1_digest,
+.len = SHA1_DIGEST_SIZE,
+},
+[QCRYPTO_HMAC_ALG_SHA256] = {
+.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha256_set_key,
+.update = (qcrypto_nettle_hmac_update)hmac_sha256_update,
+.digest = (qcrypto_nettle_hmac_digest)hmac_sha256_digest,
+.len = SHA256_DIGEST_SIZE,
+},
+[QCRYPTO_HMAC_ALG_SHA512] = {
+.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha512_set_key,
+.update = (qcrypto_nettle_hmac_update)hmac_sha512_update,
+.digest = (qcrypto_nettle_hmac_digest)hmac_sha512_digest,
+.len = SHA512_DIGEST_SIZE,
+},
+};
 
 bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg)
 {
+if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
+qcrypto_hmac_alg_map[alg].setkey != NULL) {
+return true;
+}
+
 return false;
 }
 
@@ -25,12 +82,39 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg,
   const uint8_t *key, size_t nkey,
   Error **errp)
 {
-return NULL;
+QCryptoHmac *hmac;
+QCryptoHmacNettle *ctx;
+
+if (!qcrypto_hmac_supports(alg)) {
+error_setg(errp, "Unsupported hmac algorithm %s",
+QCryptoHmacAlgorithm_lookup[alg]);
+return NULL;
+}
+
+hmac = g_new0(QCryptoHmac, 1);
+hmac->alg = alg;
+
+ctx = g_new0(QCryptoHmacNettle, 1);
+
+qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key);
+
+hmac->opaque = ctx;
+
+return hmac;
 }
 
 void qcrypto_hmac_free(QCryptoHmac *hmac)
 {
-return;
+QCryptoHmacNettle *ctx;
+
+if (!hmac) {
+return;
+}
+
+ctx = hmac->opaque;
+
+g_free(ctx);
+g_free(hmac);
 }
 
 int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
@@ -40,5 +124,33 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
 size_t *resultlen,
 Error **errp)
 {
-return -1;
+QCryptoHmacNettle *ctx;
+int i;
+
+ctx = (QCryptoHmacNettle *)hmac->opaque;
+
+for (i = 0; i < niov; ++i) {
+size_t len = iov[i].iov_len;
+uint8_t *base = iov[i].iov_base;
+while (len) {
+size_t shortlen = MIN(len, UINT_MAX);
+qcrypto_hmac_alg_map[hmac->alg].update(&ctx->u, len, base);
+len -= shortlen;
+base += len;
+}
+}
+
+if (*resultlen == 0) {
+*resultlen = qcrypto_hmac_alg_map[hmac->alg].len;
+*result = g_new0(uint8_t, *resultlen);
+} else if (*resultlen != qcrypto_hmac_alg_map[hmac->alg].len) {
+error_setg(errp,
+   "Result buffer size %zu is smaller than hash %zu",
+   *resultlen, qcrypto_hmac_alg_map[hmac->alg].len);
+return -1;
+}
+
+qcrypto_hmac_alg_map[hmac->alg].digest(&ctx->u, *resultlen, *result);
+
+return 0;
 }
-- 
1.8.3.1





[Qemu-devel] [PATCH for-2.9 v1 0/7] crypto: add HMAC algorithms support

2016-12-11 Thread Longpeng(Mike)
Since QEMU has been supported cryptodev, so it is necessary to support
more crypto algorithms(i.e. hmac,aead) in QEMU backend.

This patchset add HMAC algorithms support.

Longpeng(Mike) (7):
  qapi: crypto: add defination about HMAC algorithms
  crypto: add HMAC algorithms framework
  configure: add CONFIG_GCRYPT_SUPPORT_HMAC item
  crypto: support HMAC algorithms based on libgcrypt
  crypto: support HMAC algorithms based on glibc
  crypto: support HMAC algorithms based on nettle
  crypto: add HMAC algorithms testcases

 configure|  18 +
 crypto/Makefile.objs |   4 ++
 crypto/hmac-gcrypt.c | 182 +++
 crypto/hmac-glib.c   | 163 ++
 crypto/hmac-nettle.c | 156 
 crypto/hmac.c|  72 +++
 crypto/hmac.h| 166 ++
 qapi/crypto.json |  17 +
 tests/Makefile.include   |   2 +
 tests/test-crypto-hmac.c | 162 +
 10 files changed, 942 insertions(+)
 create mode 100644 crypto/hmac-gcrypt.c
 create mode 100644 crypto/hmac-glib.c
 create mode 100644 crypto/hmac-nettle.c
 create mode 100644 crypto/hmac.c
 create mode 100644 crypto/hmac.h
 create mode 100644 tests/test-crypto-hmac.c

-- 
1.8.3.1





[Qemu-devel] [PATCH for-2.9 v1 7/7] crypto: add HMAC algorithms testcases

2016-12-11 Thread Longpeng(Mike)
This patch add HMAC algorithms testcases

Signed-off-by: Longpeng(Mike) 
---
 tests/Makefile.include   |   2 +
 tests/test-crypto-hmac.c | 162 +++
 2 files changed, 164 insertions(+)
 create mode 100644 tests/test-crypto-hmac.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index e98d3b6..4841d58 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -91,6 +91,7 @@ gcov-files-test-qemu-opts-y = qom/test-qemu-opts.c
 check-unit-y += tests/test-write-threshold$(EXESUF)
 gcov-files-test-write-threshold-y = block/write-threshold.c
 check-unit-y += tests/test-crypto-hash$(EXESUF)
+check-unit-y += tests/test-crypto-hmac$(EXESUF)
 check-unit-y += tests/test-crypto-cipher$(EXESUF)
 check-unit-y += tests/test-crypto-secret$(EXESUF)
 check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
@@ -571,6 +572,7 @@ tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o 
$(test-qapi-obj-y)
 tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y)
 tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
 tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y)
+tests/test-crypto-hmac$(EXESUF): tests/test-crypto-hmac.o $(test-crypto-obj-y)
 tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o 
$(test-crypto-obj-y)
 tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o 
$(test-crypto-obj-y)
 tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y)
diff --git a/tests/test-crypto-hmac.c b/tests/test-crypto-hmac.c
new file mode 100644
index 000..08e1887
--- /dev/null
+++ b/tests/test-crypto-hmac.c
@@ -0,0 +1,162 @@
+/*
+ * QEMU Crypto hmac algorithms tests
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ *Longpeng(Mike) 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "crypto/init.h"
+#include "crypto/hmac.h"
+
+typedef struct QCryptoHmacTestData QCryptoHmacTestData;
+struct QCryptoHmacTestData {
+const char *path;
+QCryptoHmacAlgorithm alg;
+const char *key;
+const char *message;
+const char *digest;
+};
+
+static QCryptoHmacTestData test_data[] = {
+{
+.path = "/crypto/hmac/hmac-md5",
+.alg = QCRYPTO_HMAC_ALG_MD5,
+.key =
+"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+.message =
+"4869205468657265",
+.digest =
+"9294727a3638bb1c13f48ef8158bfc9d",
+},
+{
+.path = "/crypto/hmac/hmac-sha1",
+.alg = QCRYPTO_HMAC_ALG_SHA1,
+.key =
+"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
+"0b0b0b0b",
+.message =
+"4869205468657265",
+.digest =
+"b617318655057264e28bc0b6fb378c8e"
+"f146be00",
+},
+};
+
+static inline int unhex(char c)
+{
+if (c >= 'a' && c <= 'f') {
+return 10 + (c - 'a');
+}
+if (c >= 'A' && c <= 'F') {
+return 10 + (c - 'A');
+}
+return c - '0';
+}
+
+static inline char hex(int i)
+{
+if (i < 10) {
+return '0' + i;
+}
+return 'a' + (i - 10);
+}
+
+static size_t unhex_string(const char *hexstr,
+   uint8_t **data)
+{
+size_t len;
+size_t i;
+
+if (!hexstr) {
+*data = NULL;
+return 0;
+}
+
+len = strlen(hexstr);
+*data = g_new0(uint8_t, len / 2);
+
+for (i = 0; i < len; i += 2) {
+(*data)[i / 2] = (unhex(hexstr[i]) << 4) | unhex(hexstr[i + 1]);
+}
+return len / 2;
+}
+
+static char *hex_string(const uint8_t *bytes,
+size_t len)
+{
+char *hexstr = g_new0(char, len * 2 + 1);
+size_t i;
+
+for (i = 0; i < len; i++) {
+hexstr[i * 2] = hex((bytes[i] >> 4) & 0xf);
+hexstr[i * 2 + 1] = hex(bytes[i] & 0xf);
+}
+hexstr[len * 2] = '\0';
+
+return hexstr;
+}
+
+static void test_hmac(const void *opaque)
+{
+const QCryptoHmacTestData *data = opaque;
+size_t nkey, digest_len, msg_len;
+uint8_t *key = NULL;
+uint8_t *message = NULL;
+uint8_t *digest = NULL;
+uint8_t *output = NULL;
+char *outputhex = NULL;
+QCryptoHmac *hmac = NULL;
+Error *err = NULL;
+int ret;
+
+nkey = unhex_string(data->key, &key);
+digest_len = unhex_string(data->digest, &digest);
+msg_len = unhex_string(data->message, &message);
+
+output = g_new0(uint8_t, digest_len);
+
+hmac = qcrypto_hmac_new(data->alg, key, nkey, &err);
+g_assert(err == NULL);
+g_assert(hmac != NULL);
+
+ret = qcrypto_hmac_bytes(hmac, (const char *)message,
+msg_len, &output, &digest_len, &err);
+
+g_assert(ret == 0);
+
+outputhex = hex_string(output, digest_len);
+
+g_assert_cmpstr(outputhex, ==, data->digest);
+
+qcrypto_hmac_free(hma

[Qemu-devel] [PATCH for-2.9 v1 3/7] configure: add CONFIG_GCRYPT_SUPPORT_HMAC item

2016-12-11 Thread Longpeng(Mike)
This item will be used for support libcrypt-backed HMAC algorithms.

Support for hmac has been added in Libgcrypt 1.6.0, but we cannot
use pkg-config to get libcrypt's version. However we can make a
in configure to know whether current libcrypt support hmac.

Signed-off-by: Longpeng(Mike) 
---
 configure | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/configure b/configure
index 3770d7c..6eb5f5c 100755
--- a/configure
+++ b/configure
@@ -2417,6 +2417,21 @@ EOF
 if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
 gcrypt_kdf=yes
 fi
+
+cat > $TMPC << EOF
+#include 
+int main(void) {
+  gcry_mac_hd_t handle;
+  gcry_mac_open(&handle, GCRY_MAC_HMAC_MD5,
+GCRY_MAC_FLAG_SECURE, NULL);
+  return 0;
+}
+EOF
+if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
+gcrypy_support_hmac="yes"
+else
+gcrypy_support_hmac="no"
+fi
 else
 if test "$gcrypt" = "yes"; then
 feature_not_found "gcrypt" "Install gcrypt devel"
@@ -5387,6 +5402,9 @@ if test "$gnutls_rnd" = "yes" ; then
 fi
 if test "$gcrypt" = "yes" ; then
   echo "CONFIG_GCRYPT=y" >> $config_host_mak
+  if test "gcrypy_support_hmac" = "yes" ; then
+echo "CONFIG_GCRYPT_SUPPORT_HMAC=y" >> $config_host_mak
+  fi
   if test "$gcrypt_kdf" = "yes" ; then
 echo "CONFIG_GCRYPT_KDF=y" >> $config_host_mak
   fi
-- 
1.8.3.1





[Qemu-devel] [PATCH for-2.9 v1 5/7] crypto: support HMAC algorithms based on glibc

2016-12-11 Thread Longpeng(Mike)
This patch add glibc-backed HMAC algorithms support

Signed-off-by: Longpeng(Mike) 
---
 crypto/hmac-glib.c | 119 +
 1 file changed, 119 insertions(+)

diff --git a/crypto/hmac-glib.c b/crypto/hmac-glib.c
index 42f63c6..6a5f722 100644
--- a/crypto/hmac-glib.c
+++ b/crypto/hmac-glib.c
@@ -16,6 +16,123 @@
 #include "qapi/error.h"
 #include "crypto/hmac.h"
 
+/* Support for HMAC Algos has been added in GLib 2.30 */
+#if GLIB_CHECK_VERSION(2, 30, 0)
+
+static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
+[QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5,
+[QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1,
+[QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256,
+/* Support for HMAC SHA-512 in GLib 2.42 */
+#if GLIB_CHECK_VERSION(2, 42, 0)
+[QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512,
+#else
+[QCRYPTO_HASH_ALG_SHA512] = -1,
+#endif
+};
+
+typedef struct QCryptoHmacGlib QCryptoHmacGlib;
+struct QCryptoHmacGlib {
+GHmac *ghmac;
+};
+
+bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg)
+{
+if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
+qcrypto_hmac_alg_map[alg] != -1) {
+return true;
+}
+
+return false;
+}
+
+QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg,
+  const uint8_t *key, size_t nkey,
+  Error **errp)
+{
+QCryptoHmac *hmac;
+QCryptoHmacGlib *ctx;
+
+if (!qcrypto_hmac_supports(alg)) {
+error_setg(errp, "Unsupported hmac algorithm %s",
+QCryptoHmacAlgorithm_lookup[alg]);
+return NULL;
+}
+
+hmac = g_new0(QCryptoHmac, 1);
+hmac->alg = alg;
+
+ctx = g_new0(QCryptoHmacGlib, 1);
+
+ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg],
+(const uint8_t *)key, nkey);
+if (!ctx->ghmac) {
+error_setg(errp, "Cannot initialize hmac and set key");
+goto error;
+}
+
+hmac->opaque = ctx;
+return hmac;
+
+error:
+g_free(ctx);
+g_free(hmac);
+return NULL;
+}
+
+void qcrypto_hmac_free(QCryptoHmac *hmac)
+{
+QCryptoHmacGlib *ctx;
+
+if (!hmac) {
+return;
+}
+
+ctx = hmac->opaque;
+g_hmac_unref(ctx->ghmac);
+
+g_free(ctx);
+g_free(hmac);
+}
+
+int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
+const struct iovec *iov,
+size_t niov,
+uint8_t **result,
+size_t *resultlen,
+Error **errp)
+{
+QCryptoHmacGlib *ctx;
+int i, ret;
+
+ctx = hmac->opaque;
+
+for (i = 0; i < niov; i++) {
+g_hmac_update(ctx->ghmac, iov[i].iov_base, iov[i].iov_len);
+}
+
+ret = g_checksum_type_get_length(qcrypto_hmac_alg_map[hmac->alg]);
+if (ret < 0) {
+error_setg(errp, "Unable to get hmac length");
+return -1;
+}
+
+if (*resultlen == 0) {
+*resultlen = ret;
+*result = g_new0(uint8_t, *resultlen);
+} else if (*resultlen != ret) {
+error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
+*resultlen, ret);
+return -1;
+}
+
+g_hmac_get_digest(ctx->ghmac, *result, resultlen);
+
+return 0;
+}
+
+#else
+
 bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg)
 {
 return false;
@@ -42,3 +159,5 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
 {
 return -1;
 }
+
+#endif
-- 
1.8.3.1





Re: [Qemu-devel] [qemu patch V4 2/2] kvmclock: reduce kvmclock difference on migration

2016-12-11 Thread Pankaj Gupta

Hello Marcelo,

> 
> Check for KVM_CAP_ADJUST_CLOCK capability KVM_CLOCK_TSC_STABLE, which
> indicates that KVM_GET_CLOCK returns a value as seen by the guest at
> that moment.
> 
> For new machine types, use this value rather than reading
> from guest memory.
> 
> This reduces kvmclock difference on migration from 5s to 0.1s
> (when max_downtime == 5s).
> 
> Note: pre_save contradicts the following comment
> /*
>  * If the VM is stopped, declare the clock state valid to
>  * avoid re-reading it on next vmsave (which would return
>  * a different value). Will be reset when the VM is continued.
>  */
> But the comment is bogus: vm_state_change is never called twice in a row
> with running=0 or running=1.
> 
> Signed-off-by: Marcelo Tosatti 
> 
> ---
>  hw/i386/kvm/clock.c|  107
>  ++---
>  include/hw/i386/pc.h   |5 ++
>  target-i386/kvm.c  |7 +++
>  target-i386/kvm_i386.h |1
>  4 files changed, 106 insertions(+), 14 deletions(-)
> 
> v2:
> - improve variable names (Juan)
> - consolidate code on kvm_get_clock function (Paolo)
> - return mach_use_reliable_get_clock from needed function (Paolo)
> v3:
> - simplify check for src_use_reliable_get_clock (Eduardo)
> - move src_use_reliable_get_clock initialization to realize (Eduardo)
> 
> v4:
> - have kvm_get_clock and clock_is_reliable assignments synchronized (Eduardo)
> - add comment to the reasoning of kvmclock_pre_save (Eduardo)
> 
> 
> Index: qemu-mig-advance-clock/hw/i386/kvm/clock.c
> ===
> --- qemu-mig-advance-clock.orig/hw/i386/kvm/clock.c   2016-11-17
> 15:07:11.220632761 -0200
> +++ qemu-mig-advance-clock/hw/i386/kvm/clock.c2016-12-10 
> 13:57:58.115983966
> -0200
> @@ -36,6 +36,13 @@
>  
>  uint64_t clock;
>  bool clock_valid;
> +
> +/* whether machine type supports reliable get clock */
> +bool mach_use_reliable_get_clock;
> +
> +/* whether the 'clock' value was obtained in a host with
> + * reliable KVM_GET_CLOCK */
> +bool clock_is_reliable;
>  } KVMClockState;
>  
>  struct pvclock_vcpu_time_info {
> @@ -81,6 +88,19 @@
>  return nsec + time.system_time;
>  }
>  
> +static uint64_t kvm_get_clock(void)
> +{
> +struct kvm_clock_data data;
> +int ret;
> +
> +ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
> +if (ret < 0) {
> +fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
> +abort();
> +}
> +return data.clock;
> +}
> +
>  static void kvmclock_vm_state_change(void *opaque, int running,
>   RunState state)
>  {
> @@ -91,15 +111,23 @@
>  
>  if (running) {
>  struct kvm_clock_data data = {};
> -uint64_t time_at_migration = kvmclock_current_nsec(s);
> +uint64_t pvclock_via_mem = 0;
>  
> -s->clock_valid = false;
> +/*
> + * If the host where s->clock was read did not support reliable
> + * KVM_GET_CLOCK, read kvmclock value from memory.
> + */
> +if (!s->clock_is_reliable) {
> +pvclock_via_mem = kvmclock_current_nsec(s);
> +}
>  
> -/* We can't rely on the migrated clock value, just discard it */
> -if (time_at_migration) {
> -s->clock = time_at_migration;
> +/* We can't rely on the saved clock value, just discard it */
> +if (pvclock_via_mem) {
> +s->clock = pvclock_via_mem;
>  }
>  
> +s->clock_valid = false;
> +
>  data.clock = s->clock;
>  ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
>  if (ret < 0) {
> @@ -120,8 +148,6 @@
>  }
>  }
>  } else {
> -struct kvm_clock_data data;
> -int ret;
>  
>  if (s->clock_valid) {
>  return;
> @@ -129,13 +155,11 @@
>  
>  kvm_synchronize_all_tsc();
>  
> -ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
> -if (ret < 0) {
> -fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
> -abort();
> -}
> -s->clock = data.clock;
> -
> +s->clock = kvm_get_clock();
> +/* any code that sets s->clock needs to ensure clock_is_reliable
> + * is correctly set.
> + */
> +s->clock_is_reliable = kvm_has_adjust_clock_stable();
  
Is it required to call  'kvm_has_adjust_clock_stable' here. Is there any chance
of getting different value then in 'realize'? 

>  /*
>   * If the VM is stopped, declare the clock state valid to
>   * avoid re-reading it on next vmsave (which would return
> @@ -149,25 +173,80 @@
>  {
>  KVMClockState *s = KVM_CLOCK(dev);
>  
> +if (kvm_has_adjust_clock_stable()) {
> +s->clock_is_reliable = true;
> +}
> +
>  qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
>  }
>  
> +

Re: [Qemu-devel] [PATCH 13/21] qcow2: add .bdrv_store_persistent_dirty_bitmaps()

2016-12-11 Thread Vladimir Sementsov-Ogievskiy

10.12.2016 17:53, Max Reitz wrote:

On 09.12.2016 18:55, Vladimir Sementsov-Ogievskiy wrote:

09.12.2016 20:05, Max Reitz wrote:

On 22.11.2016 18:26, Vladimir Sementsov-Ogievskiy wrote:

Realize block bitmap storing interface, to allow qcow2 images store
persistent bitmaps.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
   block/qcow2-bitmap.c | 451
+++
   block/qcow2.c|   1 +
   block/qcow2.h|   1 +
   3 files changed, 453 insertions(+)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 81be1ca..a975388 100644
--- a/block/qcow2-bitmap.c

[...]


+return;
+}
+}
+
+/* check constraints and names */
+for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap != NULL;
+bitmap = bdrv_dirty_bitmap_next(bs, bitmap)) {

Alignment to the opening parenthesis, please.

Hmm.. without an alignment it is not so simple to distinguish for-loop
header from its body.

I know, and it's even worse for "if". That is why I usually put the
opening { on a new line if I have to spread an if/while/for header over
multiple lines.

The usual convention for qemu code is to align at an opening parenthesis
if there is one.

Admittedly, the reasoning I gave for changing checkpatch.pl to accept
opening { on a new line in certain cases was that:


Good news, didn't know)



(1) We never codified exactly what to allow for multi-line if/while/for
 conditions.
(2) It was existing practice.

(1) applies in your case also; we don't have any explicitly written-out
convention for alignment of wrapped lines. (2) is more difficult, but
there are indeed a handful of cases where lines are wrapped and not
aligned to the opening parenthesis but just indented by an additional
four spaces...

So I guess since I'm insisting on putting the opening { on a new line
for multi-line conditions, you are allowed to indent the consecutive
lines by an additional level. ;-)

(It *is* against existing convention, but I'm not in a position to argue.)


[...]


[1] What about bitmaps that have BME_FLAG_IN_USE set but do not have a
corresponding BDS bitmap?

If such a bitmap does not have BME_FLAG_AUTO set, we didn't set the
flag, so we should keep it unchanged. That's what this function is
currently doing.

However, if such a bitmap does have BME_FLAG_AUTO set, it was definitely
us who set the IN_USE flag (because otherwise we would have aborted
loading the bitmaps, and thus also aborted bdrv_open_common()).
Therefore, the only explanation is that the bitmap was deleted in the
meantime, and that means we should also delete it in the qcow2 file.

Right. Or, alternatively, these bitmaps may be deleted on corresponding
BdrvDirtyBitmap deletion.

Right, that would work, too.

Max




--
Best regards,
Vladimir




Re: [Qemu-devel] experience with SDL2, event loop & main thread

2016-12-11 Thread Fam Zheng
On Mon, 12/12 09:18, Liviu Ionescu wrote:
> 
> > On 12 Dec 2016, at 05:35, Fam Zheng  wrote:
> > 
> > Isn't it possible to notify the main thread with an EventNotifier and 
> > process
> > the deferred events in its handler?
> 
> ideally, the SDL main loop might be re-implemented asynchronously, for example
> using a pipe to pass the events, and in this case the SDL would be just a
> regular client of the main I/O loop.
> 
> any idea how difficult would be to push any changes to SDL?

Not sure I understand this question, could you be more specific?

Fam



Re: [Qemu-devel] experience with SDL2, event loop & main thread

2016-12-11 Thread Liviu Ionescu

> On 12 Dec 2016, at 09:39, Fam Zheng  wrote:
> 
>> any idea how difficult would be to push any changes to SDL?
> 
> Not sure I understand this question, could you be more specific?

I guess making SDL run asynchronously will need some major changes to the SDL 
source code, not simple patches that can be added to the QEMU build.

do you know someone who can not only implement the patches, but also push them 
to the mainstream SDL repository, to have them available to everyone?


regards,

Liviu




Re: [Qemu-devel] [PATCH for-2.9 v1 0/7] crypto: add HMAC algorithms support

2016-12-11 Thread no-reply
Hi,

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

Subject: [Qemu-devel] [PATCH for-2.9 v1 0/7] crypto: add HMAC algorithms support
Type: series
Message-id: 1481527639-17520-1-git-send-email-longpe...@huawei.com

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=16
make docker-test-quick@centos6
make docker-test-mingw@fedora
make docker-test-build@min-glib
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag] 
patchew/1481527639-17520-1-git-send-email-longpe...@huawei.com -> 
patchew/1481527639-17520-1-git-send-email-longpe...@huawei.com
Switched to a new branch 'test'
b614df7 crypto: add HMAC algorithms testcases
8ad1449 crypto: support HMAC algorithms based on nettle
ae965e0 crypto: support HMAC algorithms based on glibc
3c8ead8 crypto: support HMAC algorithms based on libgcrypt
11f716b configure: add CONFIG_GCRYPT_SUPPORT_HMAC item
c45ef52 crypto: add HMAC algorithms framework
4d98eee qapi: crypto: add defination about HMAC algorithms

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into 'dtc'...
Submodule path 'dtc': checked out '65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf'
  BUILD   centos6
make[1]: Entering directory `/var/tmp/patchew-tester-tmp-2sk4ey4p/src'
  ARCHIVE qemu.tgz
  ARCHIVE dtc.tgz
  COPYRUNNER
RUN test-quick in qemu:centos6 
Packages installed:
SDL-devel-1.2.14-7.el6_7.1.x86_64
ccache-3.1.6-2.el6.x86_64
epel-release-6-8.noarch
gcc-4.4.7-17.el6.x86_64
git-1.7.1-4.el6_7.1.x86_64
glib2-devel-2.28.8-5.el6.x86_64
libfdt-devel-1.4.0-1.el6.x86_64
make-3.81-23.el6.x86_64
package g++ is not installed
pixman-devel-0.32.8-1.el6.x86_64
tar-1.23-15.el6_8.x86_64
zlib-devel-1.2.3-29.el6.x86_64

Environment variables:
PACKAGES=libfdt-devel ccache tar git make gcc g++ zlib-devel 
glib2-devel SDL-devel pixman-devel epel-release
HOSTNAME=770fcc9f59e0
TERM=xterm
MAKEFLAGS= -j16
HISTSIZE=1000
J=16
USER=root
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES= dtc
DEBUG=
G_BROKEN_FILENAMES=1
CCACHE_HASHDIR=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu 
--prefix=/var/tmp/qemu-build/install
No C++ compiler available; disabling C++ specific optional code
Install prefix/var/tmp/qemu-build/install
BIOS directory/var/tmp/qemu-build/install/share/qemu
binary directory  /var/tmp/qemu-build/install/bin
library directory /var/tmp/qemu-build/install/lib
module directory  /var/tmp/qemu-build/install/lib/qemu
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory  /var/tmp/qemu-build/install/etc
local state directory   /var/tmp/qemu-build/install/var
Manual directory  /var/tmp/qemu-build/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path   /tmp/qemu-test/src
C compilercc
Host C compiler   cc
C++ compiler  
Objective-C compiler cc
ARFLAGS   rv
CFLAGS-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS   -I/usr/include/pixman-1-pthread -I/usr/include/glib-2.0 
-I/usr/lib64/glib-2.0/include   -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE 
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes 
-Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes 
-fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wmissing-include-dirs 
-Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self 
-Wignored-qualifiers -Wold-style-declaration -Wold-style-definition 
-Wtype-limits -fstack-protector-all
LDFLAGS   -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g 
make  make
install   install
pythonpython -B
smbd  /usr/sbin/smbd
module supportno
host CPU  x86_64
host big endian   no
target list   x86_64-softmmu aarch64-softmmu
tcg debug enabled no
gprof enabled no
sparse enabledno
strip binariesyes
profiler  no
static build  no
pixmansystem
SDL support   yes (1.2.14)
GTK support   no 
GTK GL supportno
VTE support   no 
TLS priority  NORMAL
GNUTLS supportno
GNUTLS rndno
libgcrypt no
libgcrypt kdf no
nettleno 
nettle kdfno
libtasn1  no
curses supportno
virgl support no
curl support  no
mingw32 support   no
Audio drivers oss
Block whitelist (rw) 
Block whitelist (r