Commit abbc2a2e authored by Yathindra Naik's avatar Yathindra Naik

Handle Domain-0 since it boots first

- EVTCHN_CAP_UNBOUND not needed
- This is a checkpoint for the first event channel design
- We decided to try another design which will come up next
parent 6053f260
......@@ -1005,10 +1005,10 @@ int libxl_domain_evtchn(libxl_ctx *ctx, libxl_capabilities *info, uint32_t domid
if (dom_info.shutdown || dom_info.dying)
{
printf("Remote domain %d shutdown\n!",remote_domain);
return 0;
continue;
}
if (dom_info.cap_flag)
if (dom_info.cap_flag == 1)
{
printf("Remote domain's cap_flag is set!\n");
for (port = 0; ; port++)
......@@ -1018,7 +1018,7 @@ int libxl_domain_evtchn(libxl_ctx *ctx, libxl_capabilities *info, uint32_t domid
ret = xc_evtchn_status(ctx->xch, &status);
if (ret < 0)
return 0;
break;
if ( status.status != EVTCHNSTAT_unbound && status.cap_flag != 1)
continue;
......@@ -1042,14 +1042,15 @@ int libxl_domain_evtchn(libxl_ctx *ctx, libxl_capabilities *info, uint32_t domid
}
}
}
printf("returning 0 from libxl_evtchn()\n");
return 0;
continue;
}
for ( ;num_ports > 0; num_ports--)
{
if ( (port = xc_evtchn_alloc_unbound(ctx->xch, domid, remote_domain, 1)) != -1)
/* Note: cap_flag here is 2. This is optimization instead of introducing
another argument. This indicates we are in the stage of reserving
evtchns. */
if ( (port = xc_evtchn_alloc_unbound(ctx->xch, domid, remote_domain, 2)) != -1)
{
printf("Calling xc_evtchn_getcaps\n");
cap = xc_evtchn_getcaps(ctx->xch, domid, port);
......@@ -1058,10 +1059,14 @@ int libxl_domain_evtchn(libxl_ctx *ctx, libxl_capabilities *info, uint32_t domid
printf("xc_evtchn_getcaps returned NULL\n");
else
{
printf("Calling xc_cap_grant().\n");
printf("Calling xc_cap_grant() for domid %d.\n",domid);
ret = xc_cap_grant(ctx->xch,domid,cap,1);
if (ret)
printf("xc_cap_grant failed!\n");
printf("Calling xc_cap_grant() for domid 0.\n");
ret = xc_cap_grant(ctx->xch,0,cap,1);
if (ret)
printf("xc_cap_grant failed!\n");
}
}
else
......
......@@ -285,8 +285,8 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
free(con_domid);
#ifdef CONFIG_XENCAP
state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid, 0);
state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid, 0);
state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid, 1);
state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid, 1);
#else
state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid);
state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid);
......
......@@ -120,8 +120,11 @@ static int virq_is_global(uint32_t virq)
return rc;
}
#ifdef CONFIG_XENCAP
static int get_free_port(struct domain *d, uint32_t reserve)
#else
static int get_free_port(struct domain *d)
#endif
{
struct evtchn *chn;
int port;
......@@ -131,8 +134,20 @@ static int get_free_port(struct domain *d)
return -EINVAL;
for ( port = 0; port_is_valid(d, port); port++ )
if ( evtchn_from_port(d, port)->state == ECS_FREE )
{
#ifdef CONFIG_XENCAP
chn = evtchn_from_port(d, port);
if ( reserve == 2 && chn->state == ECS_FREE )
return port;
if ( reserve == 1 && chn->state == ECS_CAP_FREE )
return port;
if ( reserve == 0 && chn->state == ECS_FREE )
return port;
#else
if ( evtchn_from_port(d, port)->state == ECS_FREE )
return port;
#endif
}
if ( port == MAX_EVTCHNS(d) )
return -ENOSPC;
......@@ -171,17 +186,23 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
spin_lock(&d->event_lock);
#ifdef CONFIG_XENCAP
if ( (port = get_free_port(d,alloc->cap_flag)) < 0 )
#else
if ( (port = get_free_port(d)) < 0 )
#endif
ERROR_EXIT_DOM(port, d);
chn = evtchn_from_port(d, port);
#ifdef CONFIG_XENCAP
chn->cap_flag = alloc->cap_flag;
if (alloc->cap_flag == 2)
chn->cap_flag = 1;
else
chn->cap_flag = alloc->cap_flag;
TT_DBG("cap_flag for channel: %d, Domain:%d, Port: %d, Remote_Domain:%d\n",alloc->cap_flag,(int)alloc->dom,port,alloc->remote_dom);
// chn->cap = NULL;
TT_DBG("calling xsm_evtchn_unbound\n");
#endif
TT_DBG("calling xsm_evtchn_unbound\n");
rc = xsm_evtchn_unbound(d, chn, alloc->remote_dom);
if ( rc )
{
......@@ -189,8 +210,31 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
goto out;
}
TT_DBG("chn->cap is %p\n",(long *)chn->cap);
chn->state = ECS_UNBOUND;
#ifdef CONFIG_XENCAP
/* First time we are here, the channel's state
is ECS_FREE and we change it to ECS_CAP_FREE.
Second time, we know that and change it to be
ECS_CAP_UNBOUND. This makes sure that get_free_port
does not return the same port again.*/
TT_DBG("chn->state before is %d\n",chn->state);
/* Note: Since dom0 is created first and there is no way to specify
dom0's config via libxl, we need this condition. It is basically
to make sure state trasistion happens correctly. For other domains,
we allocate a pool of channels when they boot and init their state
to be ECS_CAP_FREE. After the domain comes up and drivers want to
allocate evt channels, we first get a port that has state ECS_CAP_FREE,
and then we change its state to ECS_CAP_UNBOUND.*/
if (alloc->dom == 0 || alloc->dom == 32752 || alloc->remote_dom == 0 ||
(alloc->dom == 32752 && alloc->remote_dom == 32752))
chn->state = ECS_UNBOUND;
else if ((chn->cap_flag == 1) && (chn->state == ECS_FREE))
chn->state = ECS_CAP_FREE;
else
chn->state = ECS_UNBOUND;
TT_DBG("chn->state after is %d\n",chn->state);
#endif
if ( (chn->u.unbound.remote_domid = alloc->remote_dom) == DOMID_SELF )
chn->u.unbound.remote_domid = current->domain->domain_id;
......@@ -230,7 +274,13 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
spin_lock(&ld->event_lock);
}
if ( (lport = get_free_port(ld)) < 0 )
/* Note: I'm assuming cap_flag to be 0. I'm not sure
if we need cap_flag here? */
#ifdef CONFIG_XENCAP
if ( (lport = get_free_port(ld, 0)) < 0 )
#else
if ( (lport = get_free_port(ld)) < 0 )
#endif
ERROR_EXIT(lport);
lchn = evtchn_from_port(ld, lport);
......@@ -296,7 +346,11 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
if ( v->virq_to_evtchn[virq] != 0 )
ERROR_EXIT(-EEXIST);
#ifdef CONFIG_XENCAP
if ( (port = get_free_port(d,0)) < 0 )
#else
if ( (port = get_free_port(d)) < 0 )
#endif
ERROR_EXIT(port);
chn = evtchn_from_port(d, port);
......@@ -326,9 +380,12 @@ static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind)
spin_lock(&d->event_lock);
if ( (port = get_free_port(d)) < 0 )
#ifdef CONFIG_XENCAP
if ( (port = get_free_port(d,0)) < 0 )
#else
if ( (port = get_free_port(d)) < 0 )
#endif
ERROR_EXIT(port);
chn = evtchn_from_port(d, port);
chn->state = ECS_IPI;
chn->notify_vcpu_id = vcpu;
......@@ -386,8 +443,11 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
if ( pirq_to_evtchn(d, pirq) != 0 )
ERROR_EXIT(-EEXIST);
#ifdef CONFIG_XENCAP
if ( (port = get_free_port(d,0)) < 0 )
#else
if ( (port = get_free_port(d)) < 0 )
#endif
ERROR_EXIT(port);
chn = evtchn_from_port(d, port);
......@@ -1164,7 +1224,11 @@ int alloc_unbound_xen_event_channel(
spin_lock(&d->event_lock);
if ( (port = get_free_port(d)) < 0 )
#ifdef CONFIG_XENCAP
if ( (port = get_free_port(d,0)) < 0 )
#else
if ( (port = get_free_port(d)) < 0 )
#endif
goto out;
chn = evtchn_from_port(d, port);
......@@ -1240,7 +1304,11 @@ void notify_via_xen_event_channel(struct domain *ld, int lport)
int evtchn_init(struct domain *d)
{
spin_lock_init(&d->event_lock);
#ifdef CONFIG_XENCAP
if ( get_free_port(d,0) != 0 )
#else
if ( get_free_port(d) != 0 )
#endif
return -EINVAL;
evtchn_from_port(d, 0)->state = ECS_RESERVED;
......
......@@ -50,6 +50,9 @@ struct evtchn
#define ECS_PIRQ 4 /* Channel is bound to a physical IRQ line. */
#define ECS_VIRQ 5 /* Channel is bound to a virtual IRQ line. */
#define ECS_IPI 6 /* Channel is bound to a virtual IPI line. */
#ifdef CONFIG_XENCAP
#define ECS_CAP_FREE 7 /* Channel is associated with a capability and is available for use */
#endif
u8 state; /* ECS_* */
u8 xen_consumer; /* Consumer in Xen, if any? (0 = send to guest) */
u16 notify_vcpu_id; /* VCPU for local delivery notification */
......
......@@ -1569,20 +1569,27 @@ static int cap_evtchn_unbound (struct domain *d, struct evtchn *chn,
if (chn->cap_flag == 0)
return 0;
if ( chn->cap == NULL)
if (chn->cap_flag == 1)
{
TT_DBG("alloc cap for channel\n");
chn->cap = xmalloc(struct capability);
if ( chn->cap == NULL)
{
TT_DBG("alloc cap for channel\n");
chn->cap = xmalloc(struct capability);
if ( !cap_create(chn->cap) )
{
TT_DBG("cap_create returned 0x%x\n",chn->cap->magic);
return 0;
}
else
return 1;
}
else
{
TT_DBG("Cap for evtchn already alloc'ed: 0x%x\n",chn->cap->magic);
return 0; //cap is already alloc'ed
}
}
if ( !cap_create(chn->cap) )
{
TT_DBG("cap_create returned 0x%x\n",chn->cap->magic);
return 0;
}
else
return 1;
}
else
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment