Re: [Xen-devel] [PATCH v2 11/16] x86/PV: split out dealing with DRn from privileged instruction handling

2016-09-30 Thread Jan Beulich
>>> On 29.09.16 at 22:13,  wrote:
> On 28/09/16 09:15, Jan Beulich wrote:
>> This is in preparation for using the generic emulator here.
>>
>> Some care is needed temporarily to not unduly alter guest register
>> state: The local variable "res" can only go away once this code got
>> fully switched over to using x86_emulate().
>>
>> Also switch to IS_ERR_VALUE() instead of (incorrectly) open coding it.
> 
> It isn't actually an ERR_PTR().  That bit of code pre-dates the
> introduction of ERR_PTR() by some margin.
> 
> The return code of do_get_debugreg() is broken and needs fixing, along
> with the ABI of the debugreg hypercalls.
> 
> This change does cause an ABI change for PV guests, as they now can't
> read a debug register whose value is in the top 4k of linear address
> space, (ather than the top 8th of a page previously), but given that the
> ABI is already known broken, I am not sure I care too much.

Well, the way ERR_PTR() works we imply the valid errno range to
be -1...-4095. I.e. assuming a smaller range here is a latent bug
(becoming an actual one if any such value would get bubbled up
through that path). So I prefer to keep the patch the way it is,
despite its ABI effect - the implication of PV guests not being able
to fully use breakpoints on the last 8th of a page clearly has the
implication that no breakpoint should be put in the last page
anyway (and quite likely no PV guest OS has that page mapped in
the first place).

Jan


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


Re: [Xen-devel] [PATCH v2 11/16] x86/PV: split out dealing with DRn from privileged instruction handling

2016-09-29 Thread Andrew Cooper
On 28/09/16 09:15, Jan Beulich wrote:
> This is in preparation for using the generic emulator here.
>
> Some care is needed temporarily to not unduly alter guest register
> state: The local variable "res" can only go away once this code got
> fully switched over to using x86_emulate().
>
> Also switch to IS_ERR_VALUE() instead of (incorrectly) open coding it.

It isn't actually an ERR_PTR().  That bit of code pre-dates the
introduction of ERR_PTR() by some margin.

The return code of do_get_debugreg() is broken and needs fixing, along
with the ABI of the debugreg hypercalls.

This change does cause an ABI change for PV guests, as they now can't
read a debug register whose value is in the top 4k of linear address
space, (ather than the top 8th of a page previously), but given that the
ABI is already known broken, I am not sure I care too much.

Either way, keeping it like this, or switching back to the previous
opencoding, Reviewed-by: Andrew Cooper 

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


[Xen-devel] [PATCH v2 11/16] x86/PV: split out dealing with DRn from privileged instruction handling

2016-09-28 Thread Jan Beulich
This is in preparation for using the generic emulator here.

Some care is needed temporarily to not unduly alter guest register
state: The local variable "res" can only go away once this code got
fully switched over to using x86_emulate().

Also switch to IS_ERR_VALUE() instead of (incorrectly) open coding it.

Signed-off-by: Jan Beulich 

--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -2356,6 +2356,26 @@ static int priv_op_write_cr(unsigned int
 return X86EMUL_UNHANDLEABLE;
 }
 
+static int priv_op_read_dr(unsigned int reg, unsigned long *val,
+   struct x86_emulate_ctxt *ctxt)
+{
+unsigned long res = do_get_debugreg(reg);
+
+if ( IS_ERR_VALUE(res) )
+return X86EMUL_UNHANDLEABLE;
+
+*val = res;
+
+return X86EMUL_OKAY;
+}
+
+static int priv_op_write_dr(unsigned int reg, unsigned long val,
+struct x86_emulate_ctxt *ctxt)
+{
+return do_set_debugreg(reg, val) == 0
+   ? X86EMUL_OKAY : X86EMUL_UNHANDLEABLE;
+}
+
 static inline uint64_t guest_misc_enable(uint64_t val)
 {
 val &= ~(MSR_IA32_MISC_ENABLE_PERF_AVAIL |
@@ -2774,16 +2794,14 @@ static int emulate_privileged_op(struct
 break;
 
 case 0x21: /* MOV DR?, */ {
-unsigned long res;
 opcode = insn_fetch(u8, code_base, eip, code_limit);
 if ( opcode < 0xc0 )
 goto fail;
 modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
 modrm_rm  |= (opcode >> 0) & 7;
-reg = decode_register(modrm_rm, regs, 0);
-if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
+if ( priv_op_read_dr(modrm_reg, decode_register(modrm_rm, regs, 0),
+ NULL) != X86EMUL_OKAY )
 goto fail;
-*reg = res;
 break;
 }
 
@@ -2812,7 +2830,7 @@ static int emulate_privileged_op(struct
 modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
 modrm_rm  |= (opcode >> 0) & 7;
 reg = decode_register(modrm_rm, regs, 0);
-if ( do_set_debugreg(modrm_reg, *reg) != 0 )
+if ( priv_op_write_dr(modrm_reg, *reg, NULL) != X86EMUL_OKAY )
 goto fail;
 break;
 



x86/PV: split out dealing with DRn from privileged instruction handling

This is in preparation for using the generic emulator here.

Some care is needed temporarily to not unduly alter guest register
state: The local variable "res" can only go away once this code got
fully switched over to using x86_emulate().

Also switch to IS_ERR_VALUE() instead of (incorrectly) open coding it.

Signed-off-by: Jan Beulich 

--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -2356,6 +2356,26 @@ static int priv_op_write_cr(unsigned int
 return X86EMUL_UNHANDLEABLE;
 }
 
+static int priv_op_read_dr(unsigned int reg, unsigned long *val,
+   struct x86_emulate_ctxt *ctxt)
+{
+unsigned long res = do_get_debugreg(reg);
+
+if ( IS_ERR_VALUE(res) )
+return X86EMUL_UNHANDLEABLE;
+
+*val = res;
+
+return X86EMUL_OKAY;
+}
+
+static int priv_op_write_dr(unsigned int reg, unsigned long val,
+struct x86_emulate_ctxt *ctxt)
+{
+return do_set_debugreg(reg, val) == 0
+   ? X86EMUL_OKAY : X86EMUL_UNHANDLEABLE;
+}
+
 static inline uint64_t guest_misc_enable(uint64_t val)
 {
 val &= ~(MSR_IA32_MISC_ENABLE_PERF_AVAIL |
@@ -2774,16 +2794,14 @@ static int emulate_privileged_op(struct
 break;
 
 case 0x21: /* MOV DR?, */ {
-unsigned long res;
 opcode = insn_fetch(u8, code_base, eip, code_limit);
 if ( opcode < 0xc0 )
 goto fail;
 modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
 modrm_rm  |= (opcode >> 0) & 7;
-reg = decode_register(modrm_rm, regs, 0);
-if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
+if ( priv_op_read_dr(modrm_reg, decode_register(modrm_rm, regs, 0),
+ NULL) != X86EMUL_OKAY )
 goto fail;
-*reg = res;
 break;
 }
 
@@ -2812,7 +2830,7 @@ static int emulate_privileged_op(struct
 modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
 modrm_rm  |= (opcode >> 0) & 7;
 reg = decode_register(modrm_rm, regs, 0);
-if ( do_set_debugreg(modrm_reg, *reg) != 0 )
+if ( priv_op_write_dr(modrm_reg, *reg, NULL) != X86EMUL_OKAY )
 goto fail;
 break;
 
___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel