Is it possible that a
‘HYPERVISOR_event_channel_op(EVTCHNOP_send, &op)’ call can be
handled in the hypervisor in any place other than in do_event_channel_op() in
xen/common/event_channel.c ? I am seeing a failure that completely
contradicts the results of the printk’s that I have placed in the
do_event_channel_op() handler, i.e. they show no failure but the result when
seen from gdb running in the guest shows –EFAULT returned. Is
there an alternate or asynchronous path through the event channel handlers that
I should know about? This result really baffles me.
Thanks,
Phil
/************************* Printk’s in
do_event_channel_op() ************************************/
long do_event_channel_op(int cmd, XEN_GUEST_HANDLE(void)
arg)
{
long rc;
switch ( cmd )
{
.
case EVTCHNOP_send: {
struct
evtchn_send send;
int xn;
if
((xn=xcopy_from_guest(&send, arg, 1)) != 0 ) {
printk("EVTCHNOP_send: EFAULT !!! bytes remaining = %x
\n", xn);
return -EFAULT;
}
rc =
evtchn_send(send.port);
printk("EVTCHNOP_send: evtchn_send : rc = %lu port = %lu \n",
(unsigned long)rc,(unsigned long)send.port);
break;
}
static inline unsigned long
xcopy_from_user(void *to, const void __user *from, unsigned
n)
{
printk("EVTCHNOP_send1: n = %x
access_ok = %lu is_hvm_vcpu= %x \n",
n,access_ok(from,n),is_hvm_vcpu(current));
if ( access_ok(from, n) )
n = __copy_from_user(to,
from, n);
else
memset(to, 0, n);
printk("EVTCHNOP_send2: n = %x
\n", n);
return n;
}
#define xcopy_from_guest_offset(ptr, hnd, off, nr)
({ \
const typeof(*(ptr)) *_s =
(hnd).p;
\
typeof(*(ptr)) *_d =
(ptr);
\
if(is_hvm_vcpu(current))
printk("EVTCHNOP_send0: is_hvm_vcpu= %x \n",is_hvm_vcpu(current)); \
is_hvm_vcpu(current)
?
\
copy_from_user_hvm(_d, _s+(off), sizeof(*_d)*(nr))
:\
xcopy_from_user(_d, _s+(off),
sizeof(*_d)*(nr)); \
})
#define xcopy_from_guest(ptr, hnd,
nr)
\
xcopy_from_guest_offset(ptr, hnd, 0, nr)
/************************* OUTPUT
************************************/
(XEN) EVTCHNOP_send1: n = 4 access_ok = 1 is_hvm_vcpu= 0
(XEN) EVTCHNOP_send2: n = 0
(XEN) EVTCHNOP_send: evtchn_send : rc = 0 port =
2 ç======
returns zero
/************************* GDB Showing what is
actually returned ************/
(gdb) c
Continuing.
Breakpoint 1, HYPERVISOR_event_channel_op (cmd=4,
op=0xf61fd8) at ../src-xen-mini/hypervisor.c:211
211
return _hypercall2(int, xen_version,
cmd, arg);
(gdb) bt
#0 HYPERVISOR_event_channel_op (cmd=4, op=0xf61fd8) at
../src-xen-mini/hypervisor.c:211
#1 0x0037f2b9 in xencons_ring_init () at
../src-xen-mini/xencons_ring.c:100
#2 0x003853db in init_console () at
../src-xen-mini/xen_console.c:174
#3 0x00383ef6 in start_kernel
(si=0x1002000) at ../src-xen-mini/kernel.c:158
#4 0x00000014 in _start ()
(gdb) b *0x0037f2b9
Breakpoint 2 at 0x37f2b9: file
../src-xen-mini/xencons_ring.c, line 100.
(gdb) c
Continuing.
Breakpoint 2, 0x0037f2b9 in xencons_ring_init () at
../src-xen-mini/xencons_ring.c:100
100 {
(gdb) i r
eax 0xfffffff2
-14 ç=======
-EFAULT
ecx
0xf61fd8 16130008
edx
0xf61fd8 16130008
ebx
0x2 2
esp
0xf61fd0 0xf61fd0
ebp
0xf61fe0 0xf61fe0
esi
0x1002000 16785408
edi
0x1002050 16785488
eip
0x37f2b9 0x37f2b9 <xencons_ring_init+65>
eflags
0x202 [ IF ]
cs
0xe019 57369
ss
0xe021 57377
ds
0xe021 57377
es
0xe021 57377
fs
0xe021 57377
gs
0xe021 57377