[Xen-devel] [PATCH 6/9] x86/vvmx: Remove operand reading from decode_vmx_inst()

2017-10-26 Thread Euan Harris
Use operand_read() to read memory operands instead of using the value
read by decode_vmx_inst() in the following functions:

 * nvmx_handle_invept()
 * nvmx_handle_invvpid()
 * nvmx_handle_vmclear()
 * nvmx_handle_vmptrld()
 * nvmx_handle_vmxon()
 * nvmx_handle_vmwrite()

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c | 57 -
 1 file changed, 31 insertions(+), 26 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 7cda37b136..fc2123c7c0 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -456,7 +456,7 @@ gp_fault:
 
 static int decode_vmx_inst(struct cpu_user_regs *regs,
struct vmx_inst_decoded *decode,
-   unsigned long *poperandS, int vmxon_check)
+   int vmxon_check)
 {
 struct vcpu *v = current;
 union vmx_inst_info info;
@@ -473,13 +473,6 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 if ( info.fields.memreg ) {
 decode->op[0].type = VMX_INST_MEMREG_TYPE_REG;
 decode->op[0].reg_idx = info.fields.reg1;
-if ( poperandS != NULL )
-{
-int rc = operand_read(poperandS, >op[0], regs,
-  decode->op[0].len);
-if ( rc != X86EMUL_OKAY )
-return rc;
-}
 }
 else
 {
@@ -516,14 +509,6 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 
 decode->op[0].mem = base;
 decode->op[0].len = size;
-
-if ( poperandS != NULL )
-{
-int rc = operand_read(poperandS, >op[0], regs,
-  decode->op[0].len);
-if ( rc != X86EMUL_OKAY )
-return rc;
-}
 }
 
 decode->op[1].type = VMX_INST_MEMREG_TYPE_REG;
@@ -1513,7 +1498,11 @@ int nvmx_handle_vmxon(struct cpu_user_regs *regs)
 uint32_t nvmcs_revid;
 int rc;
 
-rc = decode_vmx_inst(regs, , , 1);
+rc = decode_vmx_inst(regs, , 1);
+if ( rc != X86EMUL_OKAY )
+return rc;
+
+rc = operand_read(, [0], regs, decode.op[0].len);
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1729,7 +1718,11 @@ int nvmx_handle_vmptrld(struct cpu_user_regs *regs)
 unsigned long gpa = 0;
 int rc;
 
-rc = decode_vmx_inst(regs, , , 0);
+rc = decode_vmx_inst(regs, , 0);
+if ( rc != X86EMUL_OKAY )
+return rc;
+
+rc = operand_read(, [0], regs, decode.op[0].len);
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1801,7 +1794,7 @@ int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
 unsigned long gpa = 0;
 int rc;
 
-rc = decode_vmx_inst(regs, , NULL, 0);
+rc = decode_vmx_inst(regs, , 0);
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1828,7 +1821,11 @@ int nvmx_handle_vmclear(struct cpu_user_regs *regs)
 void *vvmcs;
 int rc;
 
-rc = decode_vmx_inst(regs, , , 0);
+rc = decode_vmx_inst(regs, , 0);
+if ( rc != X86EMUL_OKAY )
+return rc;
+
+rc = operand_read(, [0], regs, decode.op[0].len);
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1879,7 +1876,7 @@ int nvmx_handle_vmread(struct cpu_user_regs *regs)
 int rc;
 unsigned long vmcs_encoding = 0;
 
-rc = decode_vmx_inst(regs, , NULL, 0);
+rc = decode_vmx_inst(regs, , 0);
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1928,10 +1925,13 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
 enum vmx_insn_errno err;
 int rc;
 
-if ( decode_vmx_inst(regs, , , 0)
- != X86EMUL_OKAY )
+if ( decode_vmx_inst(regs, , 0) != X86EMUL_OKAY )
 return X86EMUL_EXCEPTION;
 
+rc = operand_read(, [0], regs, decode.op[0].len);
+if ( rc != X86EMUL_OKAY )
+return rc;
+
 if ( vcpu_nestedhvm(v).nv_vvmcxaddr == INVALID_PADDR )
 {
 vmfail_invalid(regs);
@@ -1973,11 +1973,10 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
 int nvmx_handle_invept(struct cpu_user_regs *regs)
 {
 struct vmx_inst_decoded decode;
-unsigned long eptp;
 unsigned long invept_type = 0;
 int ret;
 
-if ( (ret = decode_vmx_inst(regs, , , 0)) != X86EMUL_OKAY )
+if ( (ret = decode_vmx_inst(regs, , 0)) != X86EMUL_OKAY )
 return ret;
 
 ret = operand_read(_type, [1], regs, decode.op[1].len);
@@ -1988,6 +1987,12 @@ int nvmx_handle_invept(struct cpu_user_regs *regs)
 {
 case INVEPT_SINGLE_CONTEXT:
 {
+unsigned long eptp;
+
+ret = operand_read(, [0], regs, decode.op[0].len);
+if ( ret )
+return ret;
+
 np2m_flush_base(current, eptp);
 break;
 }
@@ -2009,7 +2014,7 @@ int nvmx_handle_invvpid(struct cpu_user_regs *regs)
 unsigned long invvpid_type = 0;
 int ret;
 
-if ( (ret = decode_vmx_inst(regs, , NULL, 0)) != X86EMUL_OKAY )
+if ( (ret = decode_vmx

[Xen-devel] [PATCH 1/9] x86/vvmx: Remove enum vmx_regs_enc

2017-10-26 Thread Euan Harris
This is the standard register encoding, is not VVMX-specific and is only
used in a couple of places.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c|  8 
 xen/include/asm-x86/hvm/vmx/vvmx.h | 22 --
 2 files changed, 4 insertions(+), 26 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index dde02c076b..9d87786894 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -201,10 +201,10 @@ struct vmx_inst_decoded {
 unsigned long mem;
 unsigned int  len;
 };
-enum vmx_regs_enc reg1;
+unsigned int reg1;
 };
 
-enum vmx_regs_enc reg2;
+unsigned int reg2;
 };
 
 enum vmx_ops_result {
@@ -345,7 +345,7 @@ enum vmx_insn_errno set_vvmcs_real_safe(const struct vcpu 
*v, u32 encoding,
 }
 
 static unsigned long reg_read(struct cpu_user_regs *regs,
-  enum vmx_regs_enc index)
+  unsigned int index)
 {
 unsigned long *pval = decode_register(index, regs, 0);
 
@@ -353,7 +353,7 @@ static unsigned long reg_read(struct cpu_user_regs *regs,
 }
 
 static void reg_write(struct cpu_user_regs *regs,
-  enum vmx_regs_enc index,
+  unsigned int index,
   unsigned long value)
 {
 unsigned long *pval = decode_register(index, regs, 0);
diff --git a/xen/include/asm-x86/hvm/vmx/vvmx.h 
b/xen/include/asm-x86/hvm/vmx/vvmx.h
index 3285b03bbb..9ea35eb795 100644
--- a/xen/include/asm-x86/hvm/vmx/vvmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vvmx.h
@@ -64,28 +64,6 @@ struct nestedvmx {
 /* bit 0-8, and 12 must be 1 */
 #define VMX_ENTRY_CTLS_DEFAULT10x11ff
 
-/*
- * Encode of VMX instructions base on Table 24-11 & 24-12 of SDM 3B
- */
-
-enum vmx_regs_enc {
-VMX_REG_RAX,
-VMX_REG_RCX,
-VMX_REG_RDX,
-VMX_REG_RBX,
-VMX_REG_RSP,
-VMX_REG_RBP,
-VMX_REG_RSI,
-VMX_REG_RDI,
-VMX_REG_R8,
-VMX_REG_R9,
-VMX_REG_R10,
-VMX_REG_R11,
-VMX_REG_R12,
-VMX_REG_R13,
-VMX_REG_R14,
-VMX_REG_R15,
-};
 
 union vmx_inst_info {
 struct {
-- 
2.13.6


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 5/9] x86/vvmx: Replace direct calls to reg_read() with operand_read()

2017-10-26 Thread Euan Harris
Use operand_read() to read register operands in the following functions:

 * nvmx_handle_vmread()
 * nvmx_handle_vmwrite()
 * nvmx_handle_invept()

Direct reading of memory operands will be replaced in a separate patch.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c | 29 -
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 32c07eca3d..7cda37b136 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1877,6 +1877,7 @@ int nvmx_handle_vmread(struct cpu_user_regs *regs)
 pagefault_info_t pfinfo;
 u64 value = 0;
 int rc;
+unsigned long vmcs_encoding = 0;
 
 rc = decode_vmx_inst(regs, , NULL, 0);
 if ( rc != X86EMUL_OKAY )
@@ -1888,7 +1889,11 @@ int nvmx_handle_vmread(struct cpu_user_regs *regs)
 return X86EMUL_OKAY;
 }
 
-rc = get_vvmcs_safe(v, reg_read(regs, decode.op[1].reg_idx), );
+rc = operand_read(_encoding, [1], regs, decode.op[1].len);
+if ( rc != X86EMUL_OKAY )
+return rc;
+
+rc = get_vvmcs_safe(v, vmcs_encoding, );
 if ( rc != VMX_INSN_SUCCEED )
 {
 vmfail(regs, rc);
@@ -1918,9 +1923,10 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
 struct vcpu *v = current;
 struct vmx_inst_decoded decode;
 unsigned long operand; 
-u64 vmcs_encoding;
+unsigned long vmcs_encoding = 0;
 bool_t okay = 1;
 enum vmx_insn_errno err;
+int rc;
 
 if ( decode_vmx_inst(regs, , , 0)
  != X86EMUL_OKAY )
@@ -1932,7 +1938,10 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
 return X86EMUL_OKAY;
 }
 
-vmcs_encoding = reg_read(regs, decode.op[1].reg_idx);
+rc = operand_read(_encoding, [1], regs, decode.op[1].len);
+if ( rc != X86EMUL_OKAY )
+return rc;
+
 err = set_vvmcs_safe(v, vmcs_encoding, operand);
 if ( err != VMX_INSN_SUCCEED )
 {
@@ -1965,12 +1974,17 @@ int nvmx_handle_invept(struct cpu_user_regs *regs)
 {
 struct vmx_inst_decoded decode;
 unsigned long eptp;
+unsigned long invept_type = 0;
 int ret;
 
 if ( (ret = decode_vmx_inst(regs, , , 0)) != X86EMUL_OKAY )
 return ret;
 
-switch ( reg_read(regs, decode.op[1].reg_idx) )
+ret = operand_read(_type, [1], regs, decode.op[1].len);
+if ( ret != X86EMUL_OKAY )
+return ret;
+
+switch ( invept_type )
 {
 case INVEPT_SINGLE_CONTEXT:
 {
@@ -1992,12 +2006,17 @@ int nvmx_handle_invept(struct cpu_user_regs *regs)
 int nvmx_handle_invvpid(struct cpu_user_regs *regs)
 {
 struct vmx_inst_decoded decode;
+unsigned long invvpid_type = 0;
 int ret;
 
 if ( (ret = decode_vmx_inst(regs, , NULL, 0)) != X86EMUL_OKAY )
 return ret;
 
-switch ( reg_read(regs, decode.op[1].reg_idx) )
+ret = operand_read(_type, [1], regs, decode.op[1].len);
+if ( ret != X86EMUL_OKAY )
+return ret;
+
+switch ( invvpid_type )
 {
 /* Just invalidate all tlb entries for all types! */
 case INVVPID_INDIVIDUAL_ADDR:
-- 
2.13.6


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 4/9] x86/vvmx: Remove unnecessary VMX operand reads

2017-10-26 Thread Euan Harris
 * vpid is never used in nvmx_handle_invept() so there is no point in
   reading it.

 * vmptrst's operand is the memory address to which to write the VMCS
   pointer.   gpa is the pointer to write.   Reading the address into
   gpa is meaningless.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index df84592490..32c07eca3d 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1801,7 +1801,7 @@ int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
 unsigned long gpa = 0;
 int rc;
 
-rc = decode_vmx_inst(regs, , , 0);
+rc = decode_vmx_inst(regs, , NULL, 0);
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1992,10 +1992,9 @@ int nvmx_handle_invept(struct cpu_user_regs *regs)
 int nvmx_handle_invvpid(struct cpu_user_regs *regs)
 {
 struct vmx_inst_decoded decode;
-unsigned long vpid;
 int ret;
 
-if ( (ret = decode_vmx_inst(regs, , , 0)) != X86EMUL_OKAY )
+if ( (ret = decode_vmx_inst(regs, , NULL, 0)) != X86EMUL_OKAY )
 return ret;
 
 switch ( reg_read(regs, decode.op[1].reg_idx) )
-- 
2.13.6


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 9/9] x86/vvmx: Use hvm_copy_{to, from}_guest_virt() to read operands

2017-10-26 Thread Euan Harris
decode_vmx_inst() contains its own segmentation logic.This
unnecessarily duplicates segmentation code used elsewhere and contains
errors: it raises a #GP fault instead of an #SS fault for an invalid
memory access through the stack segment.

Replace this logic with hvm_copy_{to,from}_guest_virt(), which use
well-tested memory access code used in various other parts of the
hypervisor.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c | 80 +++--
 1 file changed, 26 insertions(+), 54 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 9a4e6177ad..f0a2242711 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -199,7 +199,10 @@ struct vmx_inst_decoded {
 int type;
 unsigned int bytes;
 union {
-unsigned long mem;
+struct {
+enum x86_segment seg;
+unsigned long offset;
+};
 unsigned int reg_idx;
 };
 } op[2];
@@ -380,17 +383,7 @@ static int operand_read(void *buf, struct vmx_inst_op *op,
 return X86EMUL_OKAY;
 }
 else
-{
-pagefault_info_t pfinfo;
-int rc = hvm_copy_from_guest_linear(buf, op->mem, bytes, 0, );
-
-if ( rc == HVMTRANS_bad_linear_to_gfn )
-hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
-if ( rc != HVMTRANS_okay )
-return X86EMUL_EXCEPTION;
-
-return X86EMUL_OKAY;
-}
+return hvm_copy_from_guest_virt(buf, op->seg, op->offset, bytes, 0);
 }
 
 static inline u32 __n2_pin_exec_control(struct vcpu *v)
@@ -458,9 +451,8 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 {
 struct vcpu *v = current;
 union vmx_inst_info info;
-struct segment_register seg;
-unsigned long base, index, seg_base, disp, offset;
-int scale, size;
+unsigned long base, index, disp, offset;
+int scale;
 
 unsigned int bytes = vmx_guest_x86_mode(v);
 
@@ -477,14 +469,11 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 }
 else
 {
-bool mode_64bit = (bytes == 8);
-
-decode->op[0].type = VMX_INST_MEMREG_TYPE_MEMORY;
-
 if ( info.fields.segment > x86_seg_gs )
-goto gp_fault;
-hvm_get_segment_register(v, info.fields.segment, );
-seg_base = seg.base;
+{
+ASSERT_UNREACHABLE();
+return X86EMUL_UNHANDLEABLE;
+}
 
 base = info.fields.base_reg_invalid ? 0 :
 reg_read(regs, info.fields.base_reg);
@@ -496,19 +485,12 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 
 __vmread(EXIT_QUALIFICATION, );
 
-size = 1 << (info.fields.addr_size + 1);
-
-offset = base + index * scale + disp;
-base = !mode_64bit || info.fields.segment >= x86_seg_fs ?
-   seg_base + offset : offset;
-if ( offset + size - 1 < offset ||
- (mode_64bit ?
-  !is_canonical_address((long)base < 0 ? base :
-base + size - 1) :
-  offset + size - 1 > seg.limit) )
-goto gp_fault;
+decode->op[0].type = VMX_INST_MEMREG_TYPE_MEMORY;
+decode->op[0].seg = info.fields.segment;
+decode->op[0].offset = base + index * scale + disp;
+if ( info.fields.addr_size < 2 )
+decode->op[0].offset = (uint32_t)decode->op[0].offset;
 
-decode->op[0].mem = base;
 decode->op[0].bytes = bytes;
 }
 
@@ -517,10 +499,6 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 decode->op[1].bytes = bytes;
 
 return X86EMUL_OKAY;
-
-gp_fault:
-hvm_inject_hw_exception(TRAP_gp_fault, 0);
-return X86EMUL_EXCEPTION;
 }
 
 static void vmsucceed(struct cpu_user_regs *regs)
@@ -1792,8 +1770,7 @@ int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
 struct vcpu *v = current;
 struct vmx_inst_decoded decode;
 struct nestedvcpu *nvcpu = _nestedhvm(v);
-pagefault_info_t pfinfo;
-unsigned long gpa = 0;
+uint64_t gpa;
 int rc;
 
 rc = decode_vmx_inst(regs, , 0);
@@ -1802,12 +1779,10 @@ int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
 
 gpa = nvcpu->nv_vvmcxaddr;
 
-rc = hvm_copy_to_guest_linear(decode.op[0].mem, ,
-  decode.op[0].bytes, 0, );
-if ( rc == HVMTRANS_bad_linear_to_gfn )
-hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
-if ( rc != HVMTRANS_okay )
-return X86EMUL_EXCEPTION;
+rc = hvm_copy_to_guest_virt(decode.op[0].seg, decode.op[0].offset, 
+, sizeof(gpa), 0);
+if ( rc != X86EMUL_OKAY )
+return rc;
 
 vmsucceed(regs);
 return X86EMUL_OKAY;
@@ -1873,8 +1848,7 @@ int nvmx_handle_vmread(struct cpu_user_regs *regs)
 {
 struct vcpu *v = current;
 s

[Xen-devel] [PATCH 2/9] x86/vvmx: Unify operands in struct vmx_inst_decoded

2017-10-26 Thread Euan Harris
This change prepares the way for abstracting the code which reads
memory and register operands into a generic operand_read() function in
a future patch.

Operand 1 may either be a memory location or a register, depending on
the instruction being handled.   Operand 2 may only be a register, but
it is now represented in the same way as operand 1 and so has a type
field.   This will always equal VMX_INST_MEMREG_TYPE_REG.

References to the old structure map to the new one as follows:

  mem  -> op[0].mem
  len  -> op[0].len
  reg1 -> op[0].reg
  reg2 -> op[1].reg

References to type always map to op[0].type in this patch because
previously operand 2 could only be a register and so type was never
checked when accessing it.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c | 52 -
 1 file changed, 28 insertions(+), 24 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 9d87786894..20e5e29031 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -195,16 +195,16 @@ bool_t nvmx_ept_enabled(struct vcpu *v)
 struct vmx_inst_decoded {
 #define VMX_INST_MEMREG_TYPE_MEMORY 0
 #define VMX_INST_MEMREG_TYPE_REG1
-int type;
-union {
-struct {
-unsigned long mem;
-unsigned int  len;
+struct vmx_inst_op {
+int type;
+union {
+struct {
+unsigned long mem;
+unsigned int  len;
+};
+unsigned int reg_idx;
 };
-unsigned int reg1;
-};
-
-unsigned int reg2;
+} op[2];
 };
 
 enum vmx_ops_result {
@@ -437,16 +437,16 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 info.word = offset;
 
 if ( info.fields.memreg ) {
-decode->type = VMX_INST_MEMREG_TYPE_REG;
-decode->reg1 = info.fields.reg1;
+decode->op[0].type = VMX_INST_MEMREG_TYPE_REG;
+decode->op[0].reg_idx = info.fields.reg1;
 if ( poperandS != NULL )
-*poperandS = reg_read(regs, decode->reg1);
+*poperandS = reg_read(regs, decode->op[0].reg_idx);
 }
 else
 {
 bool mode_64bit = (vmx_guest_x86_mode(v) == 8);
 
-decode->type = VMX_INST_MEMREG_TYPE_MEMORY;
+decode->op[0].type = VMX_INST_MEMREG_TYPE_MEMORY;
 
 if ( info.fields.segment > x86_seg_gs )
 goto gp_fault;
@@ -486,11 +486,13 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 if ( rc != HVMTRANS_okay )
 return X86EMUL_EXCEPTION;
 }
-decode->mem = base;
-decode->len = size;
+
+decode->op[0].mem = base;
+decode->op[0].len = size;
 }
 
-decode->reg2 = info.fields.reg2;
+decode->op[1].type = VMX_INST_MEMREG_TYPE_REG;
+decode->op[1].reg_idx = info.fields.reg2;
 
 return X86EMUL_OKAY;
 
@@ -1770,7 +1772,8 @@ int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
 
 gpa = nvcpu->nv_vvmcxaddr;
 
-rc = hvm_copy_to_guest_linear(decode.mem, , decode.len, 0, );
+rc = hvm_copy_to_guest_linear(decode.op[0].mem, ,
+  decode.op[0].len, 0, );
 if ( rc == HVMTRANS_bad_linear_to_gfn )
 hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
 if ( rc != HVMTRANS_okay )
@@ -1850,23 +1853,24 @@ int nvmx_handle_vmread(struct cpu_user_regs *regs)
 return X86EMUL_OKAY;
 }
 
-rc = get_vvmcs_safe(v, reg_read(regs, decode.reg2), );
+rc = get_vvmcs_safe(v, reg_read(regs, decode.op[1].reg_idx), );
 if ( rc != VMX_INSN_SUCCEED )
 {
 vmfail(regs, rc);
 return X86EMUL_OKAY;
 }
 
-switch ( decode.type ) {
+switch ( decode.op[0].type ) {
 case VMX_INST_MEMREG_TYPE_MEMORY:
-rc = hvm_copy_to_guest_linear(decode.mem, , decode.len, 0, 
);
+rc = hvm_copy_to_guest_linear(decode.op[0].mem, ,
+  decode.op[0].len, 0, );
 if ( rc == HVMTRANS_bad_linear_to_gfn )
 hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
 if ( rc != HVMTRANS_okay )
 return X86EMUL_EXCEPTION;
 break;
 case VMX_INST_MEMREG_TYPE_REG:
-reg_write(regs, decode.reg1, value);
+reg_write(regs, decode.op[0].reg_idx, value);
 break;
 }
 
@@ -1893,7 +1897,7 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
 return X86EMUL_OKAY;
 }
 
-vmcs_encoding = reg_read(regs, decode.reg2);
+vmcs_encoding = reg_read(regs, decode.op[1].reg_idx);
 err = set_vvmcs_safe(v, vmcs_encoding, operand);
 if ( err != VMX_INSN_SUCCEED )
 {
@@ -1931,7 +1935,7 @@ int nvmx_handle_invept(struct cpu_user_regs *regs)
 if ( (ret = decode_vmx_inst(regs, , , 0)) != X86EMUL_OKAY )
 return ret;
 
-switch ( reg_read(regs, decode.reg2) )
+switch ( reg_read

[Xen-devel] [PATCH 0/9] x86/vvmx: Read instruction operands correctly on VM exit

2017-10-26 Thread Euan Harris
decode_vmx_inst() does not read instruction operands correctly on VM exit:

 * It incorrectly uses vmx_inst_info's address_size field to calculate
   the sizes of the exit-causing instruction's operands.  The sizes of
   the operands are specified in the SDM and might depend on whether the
   guest is running in 32-bit or 64-bit mode, but they have nothing to do
   with the address_size field.

 * It includes its own segmentation logic, duplicating code elsewhere.
   This segmentation logic is also incorrect and will raise #GP fault
   rather than a #SS fault in response to an invalid memory access
   through the stack segment.
 
Patches 1-6 (up to 'Remove operand decoding from decode_vmx_inst()')
refactor decode_vmx_inst() in preparation for fixing the bugs mentioned
above.  They remove unnecessary code and extract the logic for reading
operands from decode_vmx_inst() into a new operand_read() function.
These patches should not cause any functional changes.

Patch 7 ('Use correct sizes when reading operands') replaces the incorrect
operand size calculations based on address_size with the correct sizes
from the SDM.

Patches 8 and 9 add new hvm_copy_{to,from}_guest_virt() helpers and use
them to read memory operands in place of the incorrect segmentation
logic in decode_vmx_inst().

Euan Harris (9):
  x86/vvmx: Remove enum vmx_regs_enc
  x86/vvmx: Unify operands in struct vmx_inst_decoded
  x86/vvmx: Extract operand reading logic into operand_read()
  x86/vvmx: Remove unnecessary VMX operand reads
  x86/vvmx: Replace direct calls to reg_read() with operand_read()
  x86/vvmx: Remove operand reading from decode_vmx_inst()
  x86/vvmx: Use correct sizes when reading operands
  x86/hvm: Add hvm_copy_{to,from}_guest_virt() helpers
  x86/vvmx: Use hvm_copy_{to,from}_guest_virt() to read operands

 xen/arch/x86/hvm/hvm.c |  57 ++
 xen/arch/x86/hvm/vmx/vvmx.c| 216 +
 xen/include/asm-x86/hvm/support.h  |  12 +++
 xen/include/asm-x86/hvm/vmx/vvmx.h |  22 
 4 files changed, 195 insertions(+), 112 deletions(-)

-- 
2.13.6


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 7/9] x86/vvmx: Use correct sizes when reading operands

2017-10-26 Thread Euan Harris
The sizes of VMX operands are defined in the Intel SDM and have nothing
to do with the addr_size field of struct vmx_inst_info:

invept:   r32/r64, m128
invvpid:  r32/r64, m128
vmclear:  m64
vmptrld:  m64
vmptrst:  m64
vmread:   r32/64 or m32/64, r32/64
vmwrite:  r32/r64, r32/64 or m32/64
vmon: m64

* Register operands are 32-bit or 64-bit depending on the guest mode.

* Memory operands are almost always of fixed size, usually 64-bit, but
  for vmread and vmwrite their size depends on the guest mode.

* invept has a 128-bit memory operand but the upper 64 bits are reserved
  and therefore need not be read.

* invvpid has a 128-bit memory operand but we only require the VPID value
  which lies in the lower 64 bits.

When reading variable-size operands, we pass the operand size calculated
by decode_vmx_inst() and stored in strcut vmx_inst_op.   When reading
fixed-size operands, we pass the size of the variable into which the
operand is to be read.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c | 48 +++--
 1 file changed, 25 insertions(+), 23 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index fc2123c7c0..9a4e6177ad 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -197,11 +197,9 @@ struct vmx_inst_decoded {
 #define VMX_INST_MEMREG_TYPE_REG1
 struct vmx_inst_op {
 int type;
+unsigned int bytes;
 union {
-struct {
-unsigned long mem;
-unsigned int  len;
-};
+unsigned long mem;
 unsigned int reg_idx;
 };
 } op[2];
@@ -464,6 +462,8 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 unsigned long base, index, seg_base, disp, offset;
 int scale, size;
 
+unsigned int bytes = vmx_guest_x86_mode(v);
+
 if ( vmx_inst_check_privilege(regs, vmxon_check) != X86EMUL_OKAY )
 return X86EMUL_EXCEPTION;
 
@@ -473,10 +473,11 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 if ( info.fields.memreg ) {
 decode->op[0].type = VMX_INST_MEMREG_TYPE_REG;
 decode->op[0].reg_idx = info.fields.reg1;
+decode->op[0].bytes = bytes;
 }
 else
 {
-bool mode_64bit = (vmx_guest_x86_mode(v) == 8);
+bool mode_64bit = (bytes == 8);
 
 decode->op[0].type = VMX_INST_MEMREG_TYPE_MEMORY;
 
@@ -508,11 +509,12 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 goto gp_fault;
 
 decode->op[0].mem = base;
-decode->op[0].len = size;
+decode->op[0].bytes = bytes;
 }
 
 decode->op[1].type = VMX_INST_MEMREG_TYPE_REG;
 decode->op[1].reg_idx = info.fields.reg2;
+decode->op[1].bytes = bytes;
 
 return X86EMUL_OKAY;
 
@@ -1494,7 +1496,7 @@ int nvmx_handle_vmxon(struct cpu_user_regs *regs)
 struct nestedvmx *nvmx = _2_nvmx(v);
 struct nestedvcpu *nvcpu = _nestedhvm(v);
 struct vmx_inst_decoded decode;
-unsigned long gpa = 0;
+uint64_t gpa;
 uint32_t nvmcs_revid;
 int rc;
 
@@ -1502,7 +1504,7 @@ int nvmx_handle_vmxon(struct cpu_user_regs *regs)
 if ( rc != X86EMUL_OKAY )
 return rc;
 
-rc = operand_read(, [0], regs, decode.op[0].len);
+rc = operand_read(, [0], regs, sizeof(gpa));
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1715,14 +1717,14 @@ int nvmx_handle_vmptrld(struct cpu_user_regs *regs)
 struct vcpu *v = current;
 struct vmx_inst_decoded decode;
 struct nestedvcpu *nvcpu = _nestedhvm(v);
-unsigned long gpa = 0;
+uint64_t gpa;
 int rc;
 
 rc = decode_vmx_inst(regs, , 0);
 if ( rc != X86EMUL_OKAY )
 return rc;
 
-rc = operand_read(, [0], regs, decode.op[0].len);
+rc = operand_read(, [0], regs, sizeof(gpa));
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1801,7 +1803,7 @@ int nvmx_handle_vmptrst(struct cpu_user_regs *regs)
 gpa = nvcpu->nv_vvmcxaddr;
 
 rc = hvm_copy_to_guest_linear(decode.op[0].mem, ,
-  decode.op[0].len, 0, );
+  decode.op[0].bytes, 0, );
 if ( rc == HVMTRANS_bad_linear_to_gfn )
 hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
 if ( rc != HVMTRANS_okay )
@@ -1817,7 +1819,7 @@ int nvmx_handle_vmclear(struct cpu_user_regs *regs)
 struct vmx_inst_decoded decode;
 struct nestedvcpu *nvcpu = _nestedhvm(v);
 struct nestedvmx *nvmx = _2_nvmx(v);
-unsigned long gpa = 0;
+uint64_t gpa;
 void *vvmcs;
 int rc;
 
@@ -1825,7 +1827,7 @@ int nvmx_handle_vmclear(struct cpu_user_regs *regs)
 if ( rc != X86EMUL_OKAY )
 return rc;
 
-rc = operand_read(, [0], regs, decode.op[0].len);
+rc = operand_read(, [0], regs, sizeof(gpa));
 if ( rc != X86EMUL_OKAY )
 return rc;
 
@@ -1886,7 +

[Xen-devel] [PATCH 3/9] x86/vvmx: Extract operand reading logic into operand_read()

2017-10-26 Thread Euan Harris
Extract the logic for reading operands from decode_vmx_inst() into
operand_read().   Future patches will replace operand reading logic
in elsewhere with calls to operand_read().

operand_read() must explicitly handle different operand sizes to avoid
corrupting the caller's stack.   This patch should not change the overall
behaviour of the code.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c | 59 -
 1 file changed, 47 insertions(+), 12 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 20e5e29031..df84592490 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -361,6 +361,40 @@ static void reg_write(struct cpu_user_regs *regs,
 *pval = value;
 }
 
+static int operand_read(void *buf, struct vmx_inst_op *op,
+struct cpu_user_regs *regs, unsigned int bytes)
+{
+if ( op->type == VMX_INST_MEMREG_TYPE_REG )
+{
+switch ( bytes )
+{
+case 4:
+*(uint32_t *)buf = reg_read(regs, op->reg_idx);
+
+case 8:
+*(uint64_t *)buf = reg_read(regs, op->reg_idx);
+
+default:
+ASSERT_UNREACHABLE();
+return X86EMUL_UNHANDLEABLE;
+}
+
+return X86EMUL_OKAY;
+}
+else
+{
+pagefault_info_t pfinfo;
+int rc = hvm_copy_from_guest_linear(buf, op->mem, bytes, 0, );
+
+if ( rc == HVMTRANS_bad_linear_to_gfn )
+hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
+if ( rc != HVMTRANS_okay )
+return X86EMUL_EXCEPTION;
+
+return X86EMUL_OKAY;
+}
+}
+
 static inline u32 __n2_pin_exec_control(struct vcpu *v)
 {
 return get_vvmcs(v, PIN_BASED_VM_EXEC_CONTROL);
@@ -440,7 +474,12 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
 decode->op[0].type = VMX_INST_MEMREG_TYPE_REG;
 decode->op[0].reg_idx = info.fields.reg1;
 if ( poperandS != NULL )
-*poperandS = reg_read(regs, decode->op[0].reg_idx);
+{
+int rc = operand_read(poperandS, >op[0], regs,
+  decode->op[0].len);
+if ( rc != X86EMUL_OKAY )
+return rc;
+}
 }
 else
 {
@@ -475,20 +514,16 @@ static int decode_vmx_inst(struct cpu_user_regs *regs,
   offset + size - 1 > seg.limit) )
 goto gp_fault;
 
+decode->op[0].mem = base;
+decode->op[0].len = size;
+
 if ( poperandS != NULL )
 {
-pagefault_info_t pfinfo;
-int rc = hvm_copy_from_guest_linear(poperandS, base, size,
-0, );
-
-if ( rc == HVMTRANS_bad_linear_to_gfn )
-hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
-if ( rc != HVMTRANS_okay )
-return X86EMUL_EXCEPTION;
+int rc = operand_read(poperandS, >op[0], regs,
+  decode->op[0].len);
+if ( rc != X86EMUL_OKAY )
+return rc;
 }
-
-decode->op[0].mem = base;
-decode->op[0].len = size;
 }
 
 decode->op[1].type = VMX_INST_MEMREG_TYPE_REG;
-- 
2.13.6


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 8/9] x86/hvm: Add hvm_copy_{to, from}_guest_virt() helpers

2017-10-26 Thread Euan Harris
hvm_copy_{to,from}_guest_virt() copy data to and from a guest, performing
segmentatino and paging checks on the provided seg:offset virtual address.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/hvm.c| 57 +++
 xen/include/asm-x86/hvm/support.h | 12 +
 2 files changed, 69 insertions(+)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 205b4cb685..5d2bdd6b2b 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3312,6 +3312,63 @@ unsigned long copy_from_user_hvm(void *to, const void 
*from, unsigned len)
 return rc ? len : 0; /* fake a copy_from_user() return code */
 }
 
+static int _hvm_copy_guest_virt(
+enum x86_segment seg, unsigned long offset, void *buf, unsigned int bytes,
+uint32_t pfec, unsigned int flags)
+{
+struct vcpu *curr = current;
+struct segment_register sreg, cs;
+enum hvm_translation_result res;
+pagefault_info_t pfinfo;
+unsigned long linear;
+
+ASSERT(is_x86_user_segment(seg));
+
+hvm_get_segment_register(curr, seg, );
+hvm_get_segment_register(curr, x86_seg_cs, );
+
+if ( !hvm_virtual_to_linear_addr(
+ seg, , offset, bytes,
+ flags & HVMCOPY_to_guest ? hvm_access_write : hvm_access_read,
+ , ) )
+{
+hvm_inject_hw_exception(
+(seg == x86_seg_ss) ? TRAP_stack_error : TRAP_gp_fault, 0);
+return X86EMUL_EXCEPTION;
+}
+
+if ( flags & HVMCOPY_to_guest )
+res = hvm_copy_to_guest_linear(linear, buf, bytes, pfec, );
+else
+res = hvm_copy_from_guest_linear(buf, linear, bytes, pfec, );
+
+if ( res == HVMTRANS_bad_linear_to_gfn )
+{
+hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
+return X86EMUL_EXCEPTION;
+}
+else if ( res )
+return X86EMUL_RETRY;
+
+return X86EMUL_OKAY;
+}
+
+int hvm_copy_to_guest_virt(
+enum x86_segment seg, unsigned long offset, void *buf, unsigned int bytes,
+uint32_t pfec)
+{
+return _hvm_copy_guest_virt(seg, offset, buf, bytes, pfec,
+HVMCOPY_to_guest);
+}
+
+int hvm_copy_from_guest_virt(
+void *buf, enum x86_segment seg, unsigned long offset, unsigned int bytes,
+uint32_t pfec)
+{
+return _hvm_copy_guest_virt(seg, offset, buf, bytes, pfec,
+HVMCOPY_from_guest);
+}
+
 bool hvm_check_cpuid_faulting(struct vcpu *v)
 {
 const struct msr_vcpu_policy *vp = v->arch.msr;
diff --git a/xen/include/asm-x86/hvm/support.h 
b/xen/include/asm-x86/hvm/support.h
index d784fc1856..9af2ae77b7 100644
--- a/xen/include/asm-x86/hvm/support.h
+++ b/xen/include/asm-x86/hvm/support.h
@@ -115,6 +115,18 @@ enum hvm_translation_result hvm_translate_get_page(
 pagefault_info_t *pfinfo, struct page_info **page_p,
 gfn_t *gfn_p, p2m_type_t *p2mt_p);
 
+/*
+ * Copy data to and from a guest, performing segmentation and paging checks
+ * on the provided seg:offset virtual address.
+ * Returns X86EMUL_* and raises exceptions with the current vcpu.
+ */
+int hvm_copy_to_guest_virt(
+enum x86_segment seg, unsigned long offset, void *buf, unsigned int bytes,
+uint32_t pfec);
+int hvm_copy_from_guest_virt(
+void *buf, enum x86_segment seg, unsigned long offset, unsigned int bytes,
+uint32_t pfec);
+
 #define HVM_HCALL_completed  0 /* hypercall completed - no further action */
 #define HVM_HCALL_preempted  1 /* hypercall preempted - re-execute VMCALL */
 int hvm_hypercall(struct cpu_user_regs *regs);
-- 
2.13.6


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v3 2/3] python: Extract registered watch search logic from xspy_read_watch()

2017-09-22 Thread Euan Harris
When a watch fires, xspy_read_watch() checks whether the client has
registered interest in the path which changed and, if so, returns the
path and a client-supplied token.   The binding for xs_check_watch()
needs to do the same, so this patch extracts the search code into a
separate function.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
Reviewed-by: Wei Liu <wei.l...@citrix.com>
Acked-by: Marek Marczykowski-Górecki <marma...@invisiblethingslab.com>
---
Changed since v1:
 * Remove stray newline
 * Fix indentation
---
 tools/python/xen/lowlevel/xs/xs.c | 60 ---
 1 file changed, 37 insertions(+), 23 deletions(-)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index 3a827b0..e7c3bd0 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -77,6 +77,8 @@ static inline struct xs_handle *xshandle(XsHandle *self)
 
 static void remove_watch(XsHandle *xsh, PyObject *token);
 
+static PyObject *match_watch_by_token(XsHandle *self, char **xsval);
+
 static PyObject *none(bool result);
 
 static int parse_transaction_path(XsHandle *self, PyObject *args,
@@ -484,8 +486,6 @@ static PyObject *xspy_read_watch(XsHandle *self, PyObject 
*args)
 struct xs_handle *xh = xshandle(self);
 PyObject *val = NULL;
 char **xsval;
-PyObject *token;
-int i;
 unsigned int num;
 
 if (!xh)
@@ -497,29 +497,16 @@ again:
 Py_END_ALLOW_THREADS
 if (!xsval) {
 PyErr_SetFromErrno(xs_error);
-goto exit;
-}
-if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)) != 1) {
-   xs_set_error(EINVAL);
-goto exit;
-}
-for (i = 0; i < PyList_Size(self->watches); i++) {
-if (token == PyList_GetItem(self->watches, i))
-break;
-}
-if (i == PyList_Size(self->watches)) {
-  /* We do not have a registered watch for the one that has just fired.
- Ignore this -- a watch that has been recently deregistered can still
- have watches in transit.  This is a blocking method, so go back to
- read again.
-  */
-  free(xsval);
-  goto again;
+return val;
 }
-/* Create tuple (path, token). */
-val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
- exit:
+
+val = match_watch_by_token(self, xsval);
 free(xsval);
+
+if (!val && errno == EAGAIN) {
+goto again;
+}
+
 return val;
 }
 
@@ -868,6 +855,33 @@ static int parse_transaction_path(XsHandle *self, PyObject 
*args,
 }
 
 
+static PyObject *match_watch_by_token(XsHandle *self, char **xsval)
+{
+PyObject *token;
+int i;
+
+if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)) != 1) {
+xs_set_error(EINVAL);
+return NULL;
+}
+for (i = 0; i < PyList_Size(self->watches); i++) {
+if (token == PyList_GetItem(self->watches, i))
+break;
+}
+if (i == PyList_Size(self->watches)) {
+/* We do not have a registered watch for the one that has just fired.
+   Ignore this -- a watch that has been recently deregistered can still
+   have watches in transit.
+*/
+xs_set_error(EAGAIN);
+return NULL;
+}
+
+/* Create tuple (path, token). */
+return Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
+}
+
+
 static PyObject *none(bool result)
 {
 if (result) {
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v3 1/3] python: Add binding for xs_fileno()

2017-09-22 Thread Euan Harris
xs_fileno() returns a file descriptor which receives events when Xenstore
watches fire.   Exposing this in the Python bindings is a prerequisite
for writing event-driven clients in Python.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
Reviewed-by: Wei Liu <wei.l...@citrix.com>
---
Changed since v2:
 * Use PyLong_FromLong instead of PyInt_FromLong
---
 tools/python/xen/lowlevel/xs/xs.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index aba5a20..3a827b0 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -453,6 +453,25 @@ static PyObject *xspy_watch(XsHandle *self, PyObject *args)
 }
 
 
+#define xspy_fileno_doc "\n"  \
+   "Return the FD to poll for notifications when watches fire.\n"   \
+   "Returns: [int] file descriptor.\n"\
+   "\n"
+
+static PyObject *xspy_fileno(XsHandle *self)
+{
+struct xs_handle *xh = xshandle(self);
+int fd;
+
+if (!xh)
+return NULL;
+
+fd = xs_fileno(xh);
+
+return PyLong_FromLong(fd);
+}
+
+
 #define xspy_read_watch_doc "\n"   \
"Read a watch notification.\n"  \
"\n"\
@@ -887,6 +906,7 @@ static PyMethodDef xshandle_methods[] = {
 XSPY_METH(release_domain,METH_VARARGS),
 XSPY_METH(close, METH_NOARGS),
 XSPY_METH(get_domain_path,   METH_VARARGS),
+XSPY_METH(fileno,METH_NOARGS),
 { NULL /* Sentinel. */ },
 };
 
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v3 3/3] python: Add binding for non-blocking xs_check_watch()

2017-09-22 Thread Euan Harris
xs_check_watch() checks for watch notifications without blocking.
Together with the binding for xs_fileno(), this makes it possible
to write event-driven clients in Python.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
Reviewed-by: Wei Liu <wei.l...@citrix.com>
Acked-by: Marek Marczykowski-Górecki <marma...@invisiblethingslab.com>
---
 tools/python/xen/lowlevel/xs/xs.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index e7c3bd0..9a0acfc 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -474,6 +474,33 @@ static PyObject *xspy_fileno(XsHandle *self)
 }
 
 
+#define xspy_check_watch_doc "\n"  \
+   "Check for watch notifications without blocking.\n" \
+   "\n"\
+   "Returns: [tuple] (path, token).\n" \
+   " None if no watches have fired.\n" \
+   "Raises xen.lowlevel.xs.Error on error.\n"  \
+   "\n"
+
+static PyObject *xspy_check_watch(XsHandle *self, PyObject *args)
+{
+struct xs_handle *xh = xshandle(self);
+PyObject *val = NULL;
+char **xsval;
+
+if (!xh)
+return NULL;
+
+xsval = xs_check_watch(xh);
+if (!xsval) {
+return none(errno == EAGAIN);
+}
+
+val = match_watch_by_token(self, xsval);
+free(xsval);
+return val;
+}
+
 #define xspy_read_watch_doc "\n"   \
"Read a watch notification.\n"  \
"\n"\
@@ -911,6 +938,7 @@ static PyMethodDef xshandle_methods[] = {
 XSPY_METH(set_permissions,   METH_VARARGS),
 XSPY_METH(watch, METH_VARARGS),
 XSPY_METH(read_watch,METH_NOARGS),
+XSPY_METH(check_watch,   METH_NOARGS),
 XSPY_METH(unwatch,   METH_VARARGS),
 XSPY_METH(transaction_start, METH_NOARGS),
 XSPY_METH(transaction_end,   METH_VARARGS | METH_KEYWORDS),
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v3 0/3] python: Add non-blocking Xenstore watch bindings

2017-09-22 Thread Euan Harris
Expose xs_fileno() and xs_check_watch() to Python.   These functions
make it posible to write event-driven Xenstore clients in Python:

  #!/usr/bin/env python
  
  import xen.lowlevel.xs
  
  import sys
  import errno
  from select import select
  import time
  
  # Connect to XenStore and set watch
  xsh = xen.lowlevel.xs.xs()
  xsh.watch("/foo", "footoken")
  xsh.watch("/bar", "bartoken")
  
  # Start polling loop
  xsfd = xsh.fileno()
  while True:
 readable, writable, exceptional = select([xsfd], [], [xsfd], 1.0)
 print "%d tick" % time.time()
  
 if readable:
 while True:
 watch = xsh.check_watch()
 if not watch:
 break
 path, token = watch
 print "%d watch fired: path=%s, token=%s" % (time.time(), 
  path, token)
 value = xsh.read("", path)
 print "%d read %s = %s" % (time.time(), path, value)
  
 if exceptional:
 print "select error"
  
The polling loop can be simplified further by wrapping the call to
xsh.check_watch() in a generator, but this is easier to do in Python
than in the C bindings.


Euan Harris (3):
  python: Add binding for xs_fileno()
  python: Extract registered watch search logic from  xspy_read_watch()
  python: Add binding for non-blocking xs_check_watch()

 tools/python/xen/lowlevel/xs/xs.c | 108 ++
 1 file changed, 85 insertions(+), 23 deletions(-)

-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 3/3] python: Add binding for non-blocking xs_check_watch()

2017-09-21 Thread Euan Harris
xs_check_watch() checks for watch notifications without blocking.
Together with the binding for xs_fileno(), this makes it possible
to write event-driven clients in Python.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
Reviewed-by: Wei Liu <wei.l...@citrix.com>
---
 tools/python/xen/lowlevel/xs/xs.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index 2af5e07..4710002 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -474,6 +474,33 @@ static PyObject *xspy_fileno(XsHandle *self)
 }
 
 
+#define xspy_check_watch_doc "\n"  \
+   "Check for watch notifications without blocking.\n" \
+   "\n"\
+   "Returns: [tuple] (path, token).\n" \
+   " None if no watches have fired.\n" \
+   "Raises xen.lowlevel.xs.Error on error.\n"  \
+   "\n"
+
+static PyObject *xspy_check_watch(XsHandle *self, PyObject *args)
+{
+struct xs_handle *xh = xshandle(self);
+PyObject *val = NULL;
+char **xsval;
+
+if (!xh)
+return NULL;
+
+xsval = xs_check_watch(xh);
+if (!xsval) {
+return none(errno == EAGAIN);
+}
+
+val = match_watch_by_token(self, xsval);
+free(xsval);
+return val;
+}
+
 #define xspy_read_watch_doc "\n"   \
"Read a watch notification.\n"  \
"\n"\
@@ -911,6 +938,7 @@ static PyMethodDef xshandle_methods[] = {
 XSPY_METH(set_permissions,   METH_VARARGS),
 XSPY_METH(watch, METH_VARARGS),
 XSPY_METH(read_watch,METH_NOARGS),
+XSPY_METH(check_watch,   METH_NOARGS),
 XSPY_METH(unwatch,   METH_VARARGS),
 XSPY_METH(transaction_start, METH_NOARGS),
 XSPY_METH(transaction_end,   METH_VARARGS | METH_KEYWORDS),
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 0/3] python: Add non-blocking Xenstore watch bindings

2017-09-21 Thread Euan Harris
Expose xs_fileno() and xs_check_watch() to Python.   These functions
make it posible to write event-driven Xenstore clients in Python:

  #!/usr/bin/env python
  
  import xen.lowlevel.xs
  
  import sys
  import errno
  from select import select
  import time
  
  # Connect to XenStore and set watch
  xsh = xen.lowlevel.xs.xs()
  xsh.watch("/foo", "footoken")
  xsh.watch("/bar", "bartoken")
  
  # Start polling loop
  xsfd = xsh.fileno()
  while True:
 readable, writable, exceptional = select([xsfd], [], [xsfd], 1.0)
 print "%d tick" % time.time()
  
 if readable:
 while True:
 watch = xsh.check_watch()
 if not watch:
 break
 path, token = watch
 print "%d watch fired: path=%s, token=%s" % (time.time(), 
  path, token)
 value = xsh.read("", path)
 print "%d read %s = %s" % (time.time(), path, value)
  
 if exceptional:
 print "select error"
  
The polling loop can be simplified further by wrapping the call to
xsh.check_watch() in a generator, but this is easier to do in Python
than in the C bindings.


Euan Harris (3):
  python: Add binding for xs_fileno()
  python: Extract registered watch search logic from  xspy_read_watch()
  python: Add binding for non-blocking xs_check_watch()

 tools/python/xen/lowlevel/xs/xs.c | 108 ++
 1 file changed, 85 insertions(+), 23 deletions(-)

-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 1/3] python: Add binding for xs_fileno()

2017-09-21 Thread Euan Harris
xs_fileno() returns a file descriptor which receives events when Xenstore
watches fire.   Exposing this in the Python bindings is a prerequisite
for writing event-driven clients in Python.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
Reviewed-by: Wei Liu <wei.l...@citrix.com>
---
 tools/python/xen/lowlevel/xs/xs.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index aba5a20..9f1b916 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -453,6 +453,25 @@ static PyObject *xspy_watch(XsHandle *self, PyObject *args)
 }
 
 
+#define xspy_fileno_doc "\n"  \
+   "Return the FD to poll for notifications when watches fire.\n"   \
+   "Returns: [int] file descriptor.\n"\
+   "\n"
+
+static PyObject *xspy_fileno(XsHandle *self)
+{
+struct xs_handle *xh = xshandle(self);
+int fd;
+
+if (!xh)
+return NULL;
+
+fd = xs_fileno(xh);
+
+return PyInt_FromLong(fd);
+}
+
+
 #define xspy_read_watch_doc "\n"   \
"Read a watch notification.\n"  \
"\n"\
@@ -887,6 +906,7 @@ static PyMethodDef xshandle_methods[] = {
 XSPY_METH(release_domain,METH_VARARGS),
 XSPY_METH(close, METH_NOARGS),
 XSPY_METH(get_domain_path,   METH_VARARGS),
+XSPY_METH(fileno,METH_NOARGS),
 { NULL /* Sentinel. */ },
 };
 
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 2/3] python: Extract registered watch search logic from xspy_read_watch()

2017-09-21 Thread Euan Harris
When a watch fires, xspy_read_watch() checks whether the client has
registered interest in the path which changed and, if so, returns the
path and a client-supplied token.   The binding for xs_check_watch()
needs to do the same, so this patch extracts the search code into a
separate function.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
Reviewed-by: Wei Liu <wei.l...@citrix.com>
---
Changed since v1:
 * Remove stray newline
 * Fix indentation

 tools/python/xen/lowlevel/xs/xs.c | 60 ---
 1 file changed, 37 insertions(+), 23 deletions(-)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index 9f1b916..2af5e07 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -77,6 +77,8 @@ static inline struct xs_handle *xshandle(XsHandle *self)
 
 static void remove_watch(XsHandle *xsh, PyObject *token);
 
+static PyObject *match_watch_by_token(XsHandle *self, char **xsval);
+
 static PyObject *none(bool result);
 
 static int parse_transaction_path(XsHandle *self, PyObject *args,
@@ -484,8 +486,6 @@ static PyObject *xspy_read_watch(XsHandle *self, PyObject 
*args)
 struct xs_handle *xh = xshandle(self);
 PyObject *val = NULL;
 char **xsval;
-PyObject *token;
-int i;
 unsigned int num;
 
 if (!xh)
@@ -497,29 +497,16 @@ again:
 Py_END_ALLOW_THREADS
 if (!xsval) {
 PyErr_SetFromErrno(xs_error);
-goto exit;
-}
-if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)) != 1) {
-   xs_set_error(EINVAL);
-goto exit;
-}
-for (i = 0; i < PyList_Size(self->watches); i++) {
-if (token == PyList_GetItem(self->watches, i))
-break;
-}
-if (i == PyList_Size(self->watches)) {
-  /* We do not have a registered watch for the one that has just fired.
- Ignore this -- a watch that has been recently deregistered can still
- have watches in transit.  This is a blocking method, so go back to
- read again.
-  */
-  free(xsval);
-  goto again;
+return val;
 }
-/* Create tuple (path, token). */
-val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
- exit:
+
+val = match_watch_by_token(self, xsval);
 free(xsval);
+
+if (!val && errno == EAGAIN) {
+goto again;
+}
+
 return val;
 }
 
@@ -868,6 +855,33 @@ static int parse_transaction_path(XsHandle *self, PyObject 
*args,
 }
 
 
+static PyObject *match_watch_by_token(XsHandle *self, char **xsval)
+{
+PyObject *token;
+int i;
+
+if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)) != 1) {
+xs_set_error(EINVAL);
+return NULL;
+}
+for (i = 0; i < PyList_Size(self->watches); i++) {
+if (token == PyList_GetItem(self->watches, i))
+break;
+}
+if (i == PyList_Size(self->watches)) {
+/* We do not have a registered watch for the one that has just fired.
+   Ignore this -- a watch that has been recently deregistered can still
+   have watches in transit.
+*/
+xs_set_error(EAGAIN);
+return NULL;
+}
+
+/* Create tuple (path, token). */
+return Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
+}
+
+
 static PyObject *none(bool result)
 {
 if (result) {
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 2/3] python: Extract registered watch search logic from xspy_read_watch()

2017-09-15 Thread Euan Harris
When a watch fires, xspy_read_watch() checks whether the client has
registered interest in the path which changed and, if so, returns the
path and a client-supplied token.   The binding for xs_check_watch()
needs to do the same, so this patch extracts the search code into a
separate function.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 tools/python/xen/lowlevel/xs/xs.c | 61 ---
 1 file changed, 38 insertions(+), 23 deletions(-)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index 9f1b916..a4b50a0 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -77,6 +77,8 @@ static inline struct xs_handle *xshandle(XsHandle *self)
 
 static void remove_watch(XsHandle *xsh, PyObject *token);
 
+static PyObject *match_watch_by_token(XsHandle *self, char **xsval);
+
 static PyObject *none(bool result);
 
 static int parse_transaction_path(XsHandle *self, PyObject *args,
@@ -484,8 +486,6 @@ static PyObject *xspy_read_watch(XsHandle *self, PyObject 
*args)
 struct xs_handle *xh = xshandle(self);
 PyObject *val = NULL;
 char **xsval;
-PyObject *token;
-int i;
 unsigned int num;
 
 if (!xh)
@@ -497,32 +497,20 @@ again:
 Py_END_ALLOW_THREADS
 if (!xsval) {
 PyErr_SetFromErrno(xs_error);
-goto exit;
-}
-if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)) != 1) {
-   xs_set_error(EINVAL);
-goto exit;
-}
-for (i = 0; i < PyList_Size(self->watches); i++) {
-if (token == PyList_GetItem(self->watches, i))
-break;
-}
-if (i == PyList_Size(self->watches)) {
-  /* We do not have a registered watch for the one that has just fired.
- Ignore this -- a watch that has been recently deregistered can still
- have watches in transit.  This is a blocking method, so go back to
- read again.
-  */
-  free(xsval);
-  goto again;
+return val;
 }
-/* Create tuple (path, token). */
-val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
- exit:
+
+val = match_watch_by_token(self, xsval);
 free(xsval);
+
+if (!val && errno == EAGAIN) {
+goto again;
+}
+
 return val;
 }
 
+
 #define xspy_unwatch_doc "\n"  \
"Stop watching a path.\n"   \
" path  [string] : xenstore path.\n"\
@@ -868,6 +856,33 @@ static int parse_transaction_path(XsHandle *self, PyObject 
*args,
 }
 
 
+static PyObject *match_watch_by_token(XsHandle *self, char **xsval)
+{
+PyObject *token;
+int i;
+
+if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)) != 1) {
+   xs_set_error(EINVAL);
+return NULL;
+}
+for (i = 0; i < PyList_Size(self->watches); i++) {
+if (token == PyList_GetItem(self->watches, i))
+break;
+}
+if (i == PyList_Size(self->watches)) {
+/* We do not have a registered watch for the one that has just fired.
+   Ignore this -- a watch that has been recently deregistered can still
+   have watches in transit.
+*/
+xs_set_error(EAGAIN);
+return NULL;
+}
+
+/* Create tuple (path, token). */
+return Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
+}
+
+
 static PyObject *none(bool result)
 {
 if (result) {
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 0/3] python: Add non-blocking Xenstore watch bindings

2017-09-15 Thread Euan Harris
Expose xs_fileno() and xs_check_watch() to Python.   These functions
make it posible to write event-driven Xenstore clients in Python:

  #!/usr/bin/env python
  
  import xen.lowlevel.xs
  
  import sys
  import errno
  from select import select
  import time
  
  # Connect to XenStore and set watch
  xsh = xen.lowlevel.xs.xs()
  xsh.watch("/foo", "footoken")
  xsh.watch("/bar", "bartoken")
  
  # Start polling loop
  xsfd = xsh.fileno()
  while True:
 readable, writable, exceptional = select([xsfd], [], [xsfd], 1.0)
 print "%d tick" % time.time()
  
 if readable:
 while True:
 watch = xsh.check_watch()
 if not watch:
 break
 path, token = watch
 print "%d watch fired: path=%s, token=%s" % (time.time(), 
  path, token)
 value = xsh.read("", path)
 print "%d read %s = %s" % (time.time(), path, value)
  
 if exceptional:
 print "select error"
  
The polling loop can be simplified further by wrapping the call to
xsh.check_watch() in a generator, but this is easier to do in Python
than in the C bindings.


Euan Harris (3):
  python: Add wrapper for xs_fileno()
  python: Extract registered watch search logic from  xspy_read_watch()
  python: Add binding for non-blocking xs_check_watch()

 tools/python/xen/lowlevel/xs/xs.c | 109 ++
 1 file changed, 86 insertions(+), 23 deletions(-)

-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 1/3] python: Add binding for xs_fileno()

2017-09-15 Thread Euan Harris
xs_fileno() returns a file descriptor which receives events when Xenstore
watches fire.   Exposing this in the Python bindings is a prerequisite
for writing event-driven clients in Python.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 tools/python/xen/lowlevel/xs/xs.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index aba5a20..9f1b916 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -453,6 +453,25 @@ static PyObject *xspy_watch(XsHandle *self, PyObject *args)
 }
 
 
+#define xspy_fileno_doc "\n"  \
+   "Return the FD to poll for notifications when watches fire.\n"   \
+   "Returns: [int] file descriptor.\n"\
+   "\n"
+
+static PyObject *xspy_fileno(XsHandle *self)
+{
+struct xs_handle *xh = xshandle(self);
+int fd;
+
+if (!xh)
+return NULL;
+
+fd = xs_fileno(xh);
+
+return PyInt_FromLong(fd);
+}
+
+
 #define xspy_read_watch_doc "\n"   \
"Read a watch notification.\n"  \
"\n"\
@@ -887,6 +906,7 @@ static PyMethodDef xshandle_methods[] = {
 XSPY_METH(release_domain,METH_VARARGS),
 XSPY_METH(close, METH_NOARGS),
 XSPY_METH(get_domain_path,   METH_VARARGS),
+XSPY_METH(fileno,METH_NOARGS),
 { NULL /* Sentinel. */ },
 };
 
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 3/3] python: Add binding for non-blocking xs_check_watch()

2017-09-15 Thread Euan Harris
xs_check_watch() checks for watch notifications without blocking.
Together with the binding for xs_fileno(), this makes it possible
to write event-driven clients in Python.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 tools/python/xen/lowlevel/xs/xs.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/tools/python/xen/lowlevel/xs/xs.c 
b/tools/python/xen/lowlevel/xs/xs.c
index a4b50a0..c9a9259 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -474,6 +474,33 @@ static PyObject *xspy_fileno(XsHandle *self)
 }
 
 
+#define xspy_check_watch_doc "\n"  \
+   "Check for watch notifications without blocking.\n" \
+   "\n"\
+   "Returns: [tuple] (path, token).\n" \
+   " None if no watches have fired.\n" \
+   "Raises xen.lowlevel.xs.Error on error.\n"  \
+   "\n"
+
+static PyObject *xspy_check_watch(XsHandle *self, PyObject *args)
+{
+struct xs_handle *xh = xshandle(self);
+PyObject *val = NULL;
+char **xsval;
+
+if (!xh)
+return NULL;
+
+xsval = xs_check_watch(xh);
+if (!xsval) {
+return none(errno == EAGAIN);
+}
+
+val = match_watch_by_token(self, xsval);
+free(xsval);
+return val;
+}
+
 #define xspy_read_watch_doc "\n"   \
"Read a watch notification.\n"  \
"\n"\
@@ -912,6 +939,7 @@ static PyMethodDef xshandle_methods[] = {
 XSPY_METH(set_permissions,   METH_VARARGS),
 XSPY_METH(watch, METH_VARARGS),
 XSPY_METH(read_watch,METH_NOARGS),
+XSPY_METH(check_watch,   METH_NOARGS),
 XSPY_METH(unwatch,   METH_VARARGS),
 XSPY_METH(transaction_start, METH_NOARGS),
 XSPY_METH(transaction_end,   METH_VARARGS | METH_KEYWORDS),
-- 
1.8.3.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 2/2] nested vmx: Validate host VMX MSRs before accessing them

2016-06-09 Thread Euan Harris
On Thu, Jun 09, 2016 at 06:47:55AM -0600, Jan Beulich wrote:
> >  /*
> > - * Those MSRs are available only when bit 55 of
> > - * MSR_IA32_VMX_BASIC is set.
> > + * These MSRs are only available when flags in other MSRs are set.
> > + * These prerequisites are listed in the Intel 64 and IA-32
> > + * Architectures Software Developer’s Manual, Vol 3, Appendix A.
> >   */
> > -switch ( msr )
> > -{
> > +switch ( msr ) { case MSR_IA32_VMX_PROCBASED_CTLS2:
> 
> I hope you didn't really mean to produce a garbled line like this?
> With proper formatting restored
> Reviewed-by: Jan Beulich 

Oops, definitely not.   I think this happened when I was re-wrapping
the comment above - !}fmt went further than I intended.

Sorry,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH 0/2] Validate host VMX MSRs before accessing them

2016-06-09 Thread Euan Harris
nvmx_msr_read_intercept() does not check the prerequisites before
accessing MSR_IA32_VMX_PROCBASED_CTLS2, MSR_IA32_VMX_EPT_VPID_CAP,
MSR_IA32_VMX_VMFUNC on the host.   Accessing these MSRs from a nested
VMX guest running on a host which does not support them will cause
Xen to crash with a GPF.

Euan Harris (2):
  nested vmx: Fix comment typos in nvmx_msr_read_intercept()
  nested vmx: Validate host VMX MSRs before accessing them

 xen/arch/x86/hvm/vmx/vvmx.c |   32 +++-
 1 file changed, 23 insertions(+), 9 deletions(-)

-- 
1.7.10.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH 1/2] nested vmx: Fix comment typos in nvmx_msr_read_intercept()

2016-06-09 Thread Euan Harris
Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c |   10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index faa8b69..d9493ff 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1852,7 +1852,7 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 
*msr_content)
 }
 case MSR_IA32_VMX_PINBASED_CTLS:
 case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
-/* 1-seetings */
+/* 1-settings */
 data = PIN_BASED_EXT_INTR_MASK |
PIN_BASED_NMI_EXITING |
PIN_BASED_PREEMPT_TIMER;
@@ -1862,7 +1862,7 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 
*msr_content)
 case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
 {
 u32 default1_bits = VMX_PROCBASED_CTLS_DEFAULT1;
-/* 1-seetings */
+/* 1-settings */
 data = CPU_BASED_HLT_EXITING |
CPU_BASED_VIRTUAL_INTR_PENDING |
CPU_BASED_CR8_LOAD_EXITING |
@@ -1894,7 +1894,7 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 
*msr_content)
 break;
 }
 case MSR_IA32_VMX_PROCBASED_CTLS2:
-/* 1-seetings */
+/* 1-settings */
 data = SECONDARY_EXEC_DESCRIPTOR_TABLE_EXITING |
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
SECONDARY_EXEC_ENABLE_VPID |
@@ -1906,7 +1906,7 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 
*msr_content)
 break;
 case MSR_IA32_VMX_EXIT_CTLS:
 case MSR_IA32_VMX_TRUE_EXIT_CTLS:
-/* 1-seetings */
+/* 1-settings */
 data = VM_EXIT_ACK_INTR_ON_EXIT |
VM_EXIT_IA32E_MODE |
VM_EXIT_SAVE_PREEMPT_TIMER |
@@ -1919,7 +1919,7 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 
*msr_content)
 break;
 case MSR_IA32_VMX_ENTRY_CTLS:
 case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
-/* 1-seetings */
+/* 1-settings */
 data = VM_ENTRY_LOAD_GUEST_PAT |
VM_ENTRY_LOAD_GUEST_EFER |
VM_ENTRY_LOAD_PERF_GLOBAL_CTRL |
-- 
1.7.10.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH 2/2] nested vmx: Validate host VMX MSRs before accessing them

2016-06-09 Thread Euan Harris
Some VMX MSRs may not exist on certain processor models, or may
be disabled because of configuration settings.   It is only safe to
access these MSRs if configuration flags in other MSRs are set.  These
prerequisites are listed in the Intel 64 and IA-32 Architectures
Software Developer’s Manual, Vol 3, Appendix A.

nvmx_msr_read_intercept() does not check the prerequisites before
accessing MSR_IA32_VMX_PROCBASED_CTLS2, MSR_IA32_VMX_EPT_VPID_CAP,
MSR_IA32_VMX_VMFUNC on the host.   Accessing these MSRs from a nested
VMX guest running on a host which does not support them will cause
Xen to crash with a GPF.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vvmx.c |   22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index d9493ff..ddc25bf 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1820,11 +1820,20 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 
*msr_content)
 return 0;
 
 /*
- * Those MSRs are available only when bit 55 of
- * MSR_IA32_VMX_BASIC is set.
+ * These MSRs are only available when flags in other MSRs are set.
+ * These prerequisites are listed in the Intel 64 and IA-32
+ * Architectures Software Developer’s Manual, Vol 3, Appendix A.
  */
-switch ( msr )
-{
+switch ( msr ) { case MSR_IA32_VMX_PROCBASED_CTLS2:
+if ( !cpu_has_vmx_secondary_exec_control )
+return 0;
+break;
+
+case MSR_IA32_VMX_EPT_VPID_CAP:
+if ( !(cpu_has_vmx_ept || cpu_has_vmx_vpid) )
+return 0;
+break;
+
 case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
 case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
 case MSR_IA32_VMX_TRUE_EXIT_CTLS:
@@ -1832,6 +1841,11 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 
*msr_content)
 if ( !(vmx_basic_msr & VMX_BASIC_DEFAULT1_ZERO) )
 return 0;
 break;
+
+case MSR_IA32_VMX_VMFUNC:
+if ( !cpu_has_vmx_vmfunc )
+return 0;
+break;
 }
 
 rdmsrl(msr, host_data);
-- 
1.7.10.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH] nested vmx: Intercept guest rdmsr for MSR_IA32_VMX_VMFUNC

2016-06-07 Thread Euan Harris
On Tue, Jun 07, 2016 at 04:35:28AM -0600, Jan Beulich wrote:
> > @@ -2624,7 +2624,7 @@ static int vmx_msr_read_intercept(unsigned int msr, 
> > uint64_t *msr_content)
> >  __vmread(GUEST_IA32_DEBUGCTL, msr_content);
> >  break;
> >  case IA32_FEATURE_CONTROL_MSR:
> > -case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_TRUE_ENTRY_CTLS:
> > +case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_VMFUNC:
> >  if ( !nvmx_msr_read_intercept(msr, msr_content) )
> >  goto gp_fault;
> >  break;
> 
> ... retaining this code structure makes it likely that some future
> addition will lead to the same problem again.

The safest solution would be to whitelist the MSRs which Xen handles and
which the guest should be allowed to see, rather than blacklisting which
is essentially what is happening now.   That would involve a substantial
change in the code, but aside from that is there any fundamental reason
why it would be a bad idea?

Thanks,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH] nested vmx: Intercept guest rdmsr for MSR_IA32_VMX_VMFUNC

2016-06-07 Thread Euan Harris
Guest reads of MSR_IA32_VMX_VMFUNC should be handled by
the logic in vmx_msr_read_intercept().   Otherwise a guest
can read the raw host value of this MSR, even if nested
vmx is disabled.

Signed-off-by: Euan Harris <euan.har...@citrix.com>
---
 xen/arch/x86/hvm/vmx/vmx.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 743b5a1..6c0721f 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2624,7 +2624,7 @@ static int vmx_msr_read_intercept(unsigned int msr, 
uint64_t *msr_content)
 __vmread(GUEST_IA32_DEBUGCTL, msr_content);
 break;
 case IA32_FEATURE_CONTROL_MSR:
-case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_VMFUNC:
 if ( !nvmx_msr_read_intercept(msr, msr_content) )
 goto gp_fault;
 break;
-- 
1.7.10.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH] doc: Fix nonexistent error code in libxl_event_check example

2015-07-02 Thread Euan Harris
Fix example code in comment.libxl_event_check() can return
ERROR_NOT_READY;  LIBXL_NOT_READY does not exist.

Signed-off-by: Euan Harris euan.har...@citrix.com
---
 tools/libxl/libxl_event.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/libxl/libxl_event.h b/tools/libxl/libxl_event.h
index 3c6fcfe..fad4c14 100644
--- a/tools/libxl/libxl_event.h
+++ b/tools/libxl/libxl_event.h
@@ -213,7 +213,7 @@ void libxl_evdisable_disk_eject(libxl_ctx *ctx, 
libxl_evgen_disk_eject*);
  *  libxl_osevent_afterpoll(...);
  *  for (;;) {
  *  r = libxl_event_check(...);
- *  if (r==LIBXL_NOT_READY) break;
+ *  if (r==ERROR_NOT_READY) break;
  *  if (r) goto error_out;
  *  do something with the event;
  *  }
-- 
2.4.3


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] Cancelling asynchronous operations in libxl

2015-06-24 Thread Euan Harris
Hi,

On Wed, Jan 28, 2015 at 04:57:19PM +, Ian Jackson wrote:
 Euan Harris writes (Re: Cancelling asynchronous operations in libxl):
  On Tue, Jan 20, 2015 at 04:38:24PM +, Ian Jackson wrote:
* Is an API along these lines going to meet your needs ?
  
  The API you propose for libxl_ao_cancel, as described in the comment in
  libxl.h, looks reasonable to us.The comment for ERROR_NOTIMPLEMENTED
  is a bit confusing: under what circumstances might a task actually be
  cancelled although libxl_ao_cancel returned ERROR_NOTIMPLEMENTED?
 
 A single operation may go through phases during which cancellation is
 effective, and phases during which it is not very effective because it
 hasn't been properly hooked up.  If libxl_ao_cancel is called during
 the latter, it will return ERROR_NOTIMPLEMENTED but the operation will
 still be marked as wanting-cancellation, so if it enters a phase where
 cancellation is effective, it will stop at that point.
 
 To put it another way, what libxl_ao_cancel does is:
   - find the ao in question, hopefully
   - make a note in the ao that it ought to be cancelled
   - look for something internal that has registered a
  cancellation hook
   - if such a hook was found, call it and return success;
  otherwise return ERROR_NOTIMPLEMENTED.
 
 So ERROR_NOTIMPLEMENTED is more of a hint.
 
 If you prefer, it would be possible to make libxl_ao_cancel _not_ make
 a note that the operation ought to be cancelled, in the case where
 it's returning ERROR_NOTIMPLEMENTED.  Then the libxl_ao_cancel would
 be guaranteed to have no effect.
 
 But, if we do that, it won't be possible to mark a
 currently-running-and-not-promptly-cancellable but
 maybe-shortly-actually-cancellable operation as to be cancelled.
 
 Perhaps if this is confusing the better answer is simply to return a
 different error code instead of ERROR_NOTIMPLEMENTED,
   ERROR_CANCELLATION_DIFFICULT

We've discussed the semantics of cancellation a bit more off-list and
have come to two conclusions:

  1.  The behaviour of the current libxl_ao_cancel() proposal is more akin
  to 'abort' than 'cancel'.   This is because the proposed
  implementation can't guarantee the state of the domain after
  cancellation - it might be fine, it might be dead, or it might
  be in some unanticipated limbo state, depending on just when the
  cancellation call took effect.

  We should rename the proposed libxl_ao_cancel() to libxl_ao_abort().
  This function will be defined as a best-effort way to kill an
  asynchronous operation, and will give no guarantees about the
  state of the affected domain afterwards.   We may add a true
  libxl_ao_cancel() function later, with better guarantees about the
  state of the domain afterwards.   libxl_ao_abort(), as defined here,
  covers many of our requirements in Xapi.

  2.  We should remove the ERROR_NOTIMPLEMENTED error code.It does
  not add much value, because cancellation is implemented in terms
  of underlying primitive operations, rather than API operations.
  Any async API operation may be cancellable in principle, and whether
  this error code is returned depends on exactly what primitive
  operation happens to be in progress when libxl_ao_cancel/_abort() is
  called.   Furthermore, even if the call to libxl_ao_cancel/_abort()
  returns NOTIMPLEMENTED, the operation may be cancelled anyway when
  it starts a cancellable primitive operation.

  The semantics of libxl_ao_cancel/_abort() are defined as best effort,
  so it suffices to have just two return codes:

0: The request to cancel/abort has been noted, and it may or may 
   not happen.   To find out which, check the eventual return code
   of the async operation.

ERROR_NOTFOUND: the operation to be cancelled has already completed.

Thanks,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] RFC: Proposal to improve error reporting in libxl

2015-05-20 Thread Euan Harris
Hi,

Several of us at Citrix are currently working on rewriting xenopsd -
the component of the Xapi toolstack which handles domain creation,
destruction, device attachment and so on - to use libxl instead of libxc.
One of the problems we have run into is that error reporting in libxl
is not detailed and expressive enough to let us take corrective action
or present meaningful high level error messages to users.   In particular:

  1 Many API calls return error codes, but these codes don't tell us
very much about what went wrong.   In most cases the error code is
ERROR_FAIL, ERROR_INVAL or ERROR_NOMEM.   The code may also have
been returned by a utility function and passed back unaltered by
the API call.

Examples: libxl_domain_resume, libxl_domain_remus_start (mostly
  ERROR_FAIL).   libxl_domain_rename uses ERROR_NOMEM, ERROR_INVAL
  and ERROR_FAIL.

  2 A few API calls return pointers.   In some cases a null pointer
indicates that an error occured, but in others null could possibly be
a normal return value.   If null does indicate an error, it still does
not give us any information about what happened.

Examples: libxl_list_domain, libxl_list_cpupool, libxl_list_vm

  3 A few API calls have no return value but may still log errors. 

Examples: libxl_disable_domain_death,

  4 Most API calls log detailed error messages through XTL, but there
does not seem to be a way for the caller to make use of them.  Some
error messages may also have been logged by utility functions, not
by the API call itself.

We would like to make libxl's error reporting more regular and informative
for callers.We think we need to:

  * Make a list of the error conditions which can be encountered by
all the current API calls and define a set of error codes to
cover them.   Some codes will be generally applicable, but give
more information than a bare 'fail'; others may be specific to a
particular API call.   We may keep the existing FAIL, INVAL and 
NOMEM codes for times when they are appropriate.

The error messages logged by each API call are a good starting point
for this list.   I have included a partial list below.

  * Change the API calls in point 1 above to use the new, more detailed
error codes.   These changes will break client code which checks for
particular error codes, rather than just checking whether the return
code is non-zero.

  * For the API calls in points 2 and 3 which can encounter errors
which callers might care about, change their interfaces to return
error codes.   For functions which previously returned pointers,
add pointer-to-pointer parameters.

  * For error codes returned by utility functions, described in point 4, 
decide whether the code can be reported directly or an API-level
error should be reported instead.

These changes will certainly require a new version of the libxl API.   We
have considered other options which would be less likely to break existing
code - in particular the option of keeping the existing return codes but
adding an errno-like field which could contain a more specific error number.
This approach would not break existing client code and would allow API calls
which return void or pointers to report errors.   However there is no obvious
place to put the errno field - the ctx struct is not suitable because it might
be used by several callers simultaneously.The API-breaking change outlined
above seems to be the cleanest option, although it requires work on both libxl
and its clients.

All comments on this proposal are very welcome.   Examples of API calls
which would not fit well into the new design would be particularly useful.
We are also keen to hear whether or not these changes would be useful
for libvirt and other toolstacks using libxl, and whether those toolstacks
have encountered any other error reporting problems which we have missed.

Thanks,
Euan



Notes on some API functions defined in libxl.c.

'ERROR_FOO, string' means that when ERROR_FOO is returned, string
is also logged.   In most non-trivial functions, error reporting is
handled as follows:
   * store the error code in 'rc' or a similar local variable 
   * log the error string
   * goto the 'out' or 'out_err' label at the end of the function
   

libxl_ctx_alloc:
  success: 0
  failure:
ERROR_VERSION
ERROR_FAIL, Failed to initialize mutex
ERROR_FAIL, cannot open libxc handle
ERROR_FAIL, cannot connect to xenstore
ERROR_FAIL, cannot open libxc evtchn handle (from libxl__ctx_evtchn_init) 

libxl_ctx_free:
  success: 0
  no errors
  
libxl_string_list_dispose:
  no return value
  no interesting failure modes apart from segfault

libxl_string_list_copy:
libxl_key_value_list_copy
  no return value
  if calloc fails, logs libxl: FATAL ERROR: memory allocation failure and 
exits
  if strdup fails, logs libxl: FATAL ERROR: memory allocation failure and 
exits


Re: [Xen-devel] [RFC PATCH v2 00/29] libxl: Cancelling asynchronous operations

2015-04-09 Thread Euan Harris
On Tue, Apr 07, 2015 at 06:19:52PM +0100, Ian Jackson wrote:
 On the contrary, I think many long-running operations, such as suspend
 and migrations, involve multiple iterations of the libxl event loop.
 Actual suspend/migrate is done in a helper process; the main process
 is responsible for progress report handling, coordination, etc.

Yes, that would work, but an open loop approach like that can lead to
frustratingly unreliable tests.   I think it would be best to make
the test aware of the state of the helper - or even in control of it.
That would allow us to wait for the helper to reach a particular state
before killing it.

Thanks,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC PATCH v2 00/29] libxl: Cancelling asynchronous operations

2015-04-07 Thread Euan Harris
Hi,

On Wed, Feb 18, 2015 at 04:10:35PM +, Euan Harris wrote:
 We had a chat about testing these changes, and integrating them into xenopsd.
 We agreed that we each had slightly different expectations of what we were 
 going to do, and when.   I think we came to the following major conclusions:
 
   - I will start work on a simple test framework for cancellation,
 hopefully to have first results in a fortnight or so.
   - Once the test framework is available you will fix whatever bugs it
 unearths, then we will rinse and repeat.
   - You will think some more about the possibility of adding cancellation
 to the xl command line tool, but since this is tricky there is no 
 expectation of when it might happen.

I think the most straightforward way to test the cancellation mechanism in
LibXL will be to adapt the way we test similar functionality in xenopsd:

   * define numbered 'cancellation points' at which cancellable operations
 can be cancelled
   * before testing a cancellable operation, pre-set the cancellation point
 at which cancellation should be attempted
   * when execution reaches the pre-set cancellation point, run the cancellation
 procedure

This approach alone will not allow us to test asynchronous cancellation in
the middle of long-running operations, such as writing a suspend image
to disk - that will require a way to synchronize the test program with
the long-running operation.

My first guess about how this might be done was:

   * add current cancellation point and a trigger point variables to the context
 struct
   * increment the counter and fire the cancellation logic in
 libxl__ao_cancellable_register()

In this way we could write a loop which iterated through all possible
cancellation points.   However you pointed out that we cannot call
libxl_ao_cancel() while holding the context lock, so this idea needs
some refinement.   One possibility would be to tell another thread to try
to do the cancellation immediately after we release the lock;  another
option, if we didn't want to write a multi-thread test driver,
would be to do the cancellation at the top of libxl's event loop.

I think this captures roughly what we talked about.   Please let me know
if I misunderstood or missed out any details.

Thanks,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC PATCH v2 00/29] libxl: Cancelling asynchronous operations

2015-03-20 Thread Euan Harris
On Tue, Mar 03, 2015 at 12:08:04PM +, Ian Campbell wrote:
  I wouldn't recommend testing it yet until I've at least smoke tested
  it to see that things still work if you don't cancel them.
 
 Would review of the series be useful and/or appreciated at this stage?
 
 Perhaps the first half dozen or so look like preparatory cleanups which
 I could sensibly look at?

Yes, that would be great.   I've read through the whole series fairly carefully,
and it looks sensible, but you will be better placed to see whether it fits well
with the rest of libxl.

Thanks,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC PATCH v2 00/29] libxl: Cancelling asynchronous operations

2015-02-18 Thread Euan Harris
Hi,

On Tue, Feb 10, 2015 at 08:09:47PM +, Ian Jackson wrote:
 I have rebased this onto current staging.  I have compiled it but
 NOT EXECUTED IT AT ALL.  Euan, I thought it would be useful to give
 you something you could start to work on building against.
 
 I wouldn't recommend testing it yet until I've at least smoke tested
 it to see that things still work if you don't cancel them.

We had a chat about testing these changes, and integrating them into xenopsd.
We agreed that we each had slightly different expectations of what we were 
going to do, and when.   I think we came to the following major conclusions:

  - I will start work on a simple test framework for cancellation,
hopefully to have first results in a fortnight or so.
  - Once the test framework is available you will fix whatever bugs it
unearths, then we will rinse and repeat.
  - You will think some more about the possibility of adding cancellation
to the xl command line tool, but since this is tricky there is no 
expectation of when it might happen.

In the slightly longer term, we expect:

  - More testing and integration effort from Xapi project members in March
or April.
  - Investigation of the idea of a xenopsd-based push gate, similar to the 
current libvirt push gate.

Have I got the main points right, or forgotten anything important?   

Thanks,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH] tools: work around collision of -O0 and -D_FORTIFY_SOURCE

2015-02-05 Thread Euan Harris
On Thu, Feb 05, 2015 at 03:26:00PM +, Ian Jackson wrote:
 Jan Beulich writes (Re: [PATCH] tools: work around collision of -O0 and 
 -D_FORTIFY_SOURCE):
  For one, PY_XCFLAGS='' wouldn't help, as we get -O0 from the
  incoming CFLAGS.
 
 Sorry, I meant PY_XCFLAGS='' or -O1 (as appropriate).
 
  And then I'm not really intending to fiddle with
  the configure scripts (albeit, having done the patch in the presented
  form, I expected you to want it done that way) - this and alike is
  what I specifically want to stay out of if at all possible. Since in any
  event commit 1166ecf781 introduced a regression for multiple
  people, perhaps if that is not supposed to be reverted Euan should
  look into addressing that regression?
 
 Since I'm being difficult, how about if I prepare patch to configure.
 Would you be able to test it ?

If it's not too much trouble, I'd be very grateful if you could do this.
My autotools knowledge is rusty, and I don't know when I'll have the 
opportunity to set up a machine which reproduces the problem (clearly
mine doesn't, otherwise I would have run into this problem before!)

Thanks,
Euan


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] Cancelling asynchronous operations in libxl

2015-01-28 Thread Euan Harris
Hi,

On Tue, Jan 20, 2015 at 04:38:24PM +, Ian Jackson wrote:
  * Is an API along these lines going to meet your needs ?

The API you propose for libxl_ao_cancel, as described in the comment in
libxl.h, looks reasonable to us.The comment for ERROR_NOTIMPLEMENTED
is a bit confusing: under what circumstances might a task actually be
cancelled although libxl_ao_cancel returned ERROR_NOTIMPLEMENTED?

  * Can you help me test it ?  Trying to test this in xl is going to be
awkward and involve a lot of extraneous and very complicated signal
handling; and AFAIAA libvirt doesn't have any cancellation
facility.

Yes, of course.   However, wouldn't it also be useful for xl to gain
the ability to cancel long-running operations by handling SIGINT?

  * Any further comments (eg, re timescales etc).

None that we can think of at the moment.

Thanks,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH] libxl/Makefile: Don't optimize debug builds; add macro debugging information

2014-12-01 Thread Euan Harris
libxl debug builds are built with optimization level -O1, inherited from
the CFLAGS definition in StdGNU.mk.   Optimizations confuse the debugger,
and the comment justifying -O1 in StdGNU.mk should not apply for a
userspace library.   Disable optimization by appending -O0 to CFLAGS,
which overrides the -O1 flag specified earlier.

Also specify -g3, to add macro debugging information which allows
gdb to expand macro invocations.   This is useful as libxl uses many
non-trivial macros.

Signed-off-by: Euan Harris euan.har...@citrix.com
---
 tools/libxl/Makefile |6 ++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index df08c8a..26d8679 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -15,6 +15,12 @@ CFLAGS += -Werror -Wno-format-zero-length 
-Wmissing-declarations \
-Wno-declaration-after-statement -Wformat-nonliteral
 CFLAGS += -I. -fPIC
 
+ifeq ($(debug),y)
+# Disable optimizations and debugging information for macros
+CFLAGS += -O0 -g3
+endif
+
+
 ifeq ($(CONFIG_Linux),y)
 LIBUUID_LIBS += -luuid
 endif
-- 
1.7.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH] libxl: libxl_domain_info: fix typo in error message

2014-12-01 Thread Euan Harris
Signed-off-by: Euan Harris euan.har...@citrix.com
---
 tools/libxl/libxl.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index f84f7c2..c50c323 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -674,7 +674,7 @@ int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r,
 
 ret = xc_domain_getinfolist(ctx-xch, domid, 1, xcinfo);
 if (ret0) {
-LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, geting domain info list);
+LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, getting domain info list);
 return ERROR_FAIL;
 }
 if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL;
-- 
1.7.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] libxl: Is the nic param to libxl_network_device_add an (in)_out parameter?

2014-11-18 Thread Euan Harris
Hi,

If I call libxl_device_nic_add and pass in a mostly-default
libxl_device_nic structure, the function fills in the unspecified default
config fields with data for the NIC which it has just created:

libxl_device_nic nic;
libxl_device_nic_init(nic);
/* 
   nic.devid == -1 
   nic.mac == 00:00:00:00:00:00 
   nic.model == null
   etc.
 */

libxl_device_nic_add(ctx, domid, nic, NULL);
/* 
   nic.devid == 3 
   nic.mac == 00:16:3e:1b:7b:12
   nic.model == rtl8139
   etc.
 */

Is this behaviour an intentional part of the API which I can rely on,
or just an artefact of the current implementation?  In other words, is
nic meant to be an (in)_out parameter?  If it's not, what is the correct
way to find out the device ID which was allocated for the new device,
for example?

Thanks,
Euan

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH] libxl: Document device parameter of libxl_device_type_add functions

2014-11-18 Thread Euan Harris
The device parameter of libxl_device_type_add is an in/out parameter.
Unspecified fields are filled in with appropriate values for the created
device when the function returns.  Document this behaviour.

Signed-off-by: Euan Harris euan.har...@citrix.com
---
 tools/libxl/libxl.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index c3451bd..41d6e8d 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1109,6 +1109,10 @@ void libxl_vtpminfo_list_free(libxl_vtpminfo *, int 
nr_vtpms);
  *   domain to connect to the device and therefore cannot block on the
  *   guest.
  *
+ *   device is an in/out parameter:  fields left unspecified when the
+ *   structure is passed in are filled in with appropriate values for
+ *   the device created.
+ *
  * libxl_device_type_remove(ctx, domid, device):
  *
  *   Removes the given device from the specified domain by performing
-- 
1.9.3


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel