do_poll takes sched_poll* as parameter, but that's actually in guest memory (so it's more a guest handle). Split its copy from/to guest logic from the main logic, so that we have a separate vcpu_poll which takes the sched_poll parameters directly.
Signed-off-by: Teddy Astie <teddy.as...@vates.tech> --- xen/common/sched/core.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c index 13fdf57e57..b2c784c60e 100644 --- a/xen/common/sched/core.c +++ b/xen/common/sched/core.c @@ -1437,21 +1437,13 @@ static void vcpu_block_enable_events(void) vcpu_block(); } -static long do_poll(const struct sched_poll *sched_poll) +static long vcpu_poll(unsigned int nr_ports, uint64_t timeout, evtchn_port_t *ports) { struct vcpu *v = current; struct domain *d = v->domain; - evtchn_port_t port = 0; long rc; unsigned int i; - /* Fairly arbitrary limit. */ - if ( sched_poll->nr_ports > 128 ) - return -EINVAL; - - if ( !guest_handle_okay(sched_poll->ports, sched_poll->nr_ports) ) - return -EFAULT; - set_bit(_VPF_blocked, &v->pause_flags); v->poll_evtchn = -1; set_bit(v->vcpu_id, d->poll_mask); @@ -1478,13 +1470,9 @@ static long do_poll(const struct sched_poll *sched_poll) if ( local_events_need_delivery() ) goto out; - for ( i = 0; i < sched_poll->nr_ports; i++ ) + for ( i = 0; i < nr_ports; i++ ) { - rc = -EFAULT; - if ( __copy_from_guest_offset(&port, sched_poll->ports, i, 1) ) - goto out; - - rc = evtchn_port_poll(d, port); + rc = evtchn_port_poll(d, ports[i]); if ( rc ) { if ( rc > 0 ) @@ -1493,11 +1481,11 @@ static long do_poll(const struct sched_poll *sched_poll) } } - if ( sched_poll->nr_ports == 1 ) - v->poll_evtchn = port; + if ( nr_ports == 1 ) + v->poll_evtchn = ports[0]; - if ( sched_poll->timeout != 0 ) - set_timer(&v->poll_timer, sched_poll->timeout); + if ( timeout != 0 ) + set_timer(&v->poll_timer, timeout); TRACE_TIME(TRC_SCHED_BLOCK, d->domain_id, v->vcpu_id); raise_softirq(SCHEDULE_SOFTIRQ); @@ -1511,6 +1499,20 @@ static long do_poll(const struct sched_poll *sched_poll) return rc; } +static long do_poll(struct sched_poll *sched_poll) +{ + evtchn_port_t ports[128]; + + /* Fairly arbitrary limit */ + if ( sched_poll->nr_ports > 128 ) + return -EINVAL; + + if ( copy_from_guest(ports, sched_poll->ports, sched_poll->nr_ports) ) + return -EFAULT; + + return vcpu_poll(sched_poll->nr_ports, sched_poll->timeout, ports); +} + /* Voluntarily yield the processor for this allocation. */ long vcpu_yield(void) { -- 2.50.1 Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech