All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wei Liu <wei.liu2@citrix.com>
To: Bhupinder Thakur <bhupinder.thakur@linaro.org>
Cc: xen-devel@lists.xenproject.org,
	Julien Grall <julien.grall@arm.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	Wei Liu <wei.liu2@citrix.com>
Subject: Re: [PATCH 08/10] xen/arm: vpl011: Modify the APIs in xenconsole to acces both PV and VCON consoles
Date: Wed, 12 Apr 2017 17:33:15 +0100	[thread overview]
Message-ID: <20170412163315.ns7kqxvesrxei5ev@citrix.com> (raw)
In-Reply-To: <1491212673-13476-9-git-send-email-bhupinder.thakur@linaro.org>

On Mon, Apr 03, 2017 at 03:14:31PM +0530, Bhupinder Thakur wrote:
> Xenconsole supports only PV console currently. To get access to emulated pl011
> uart another backend console is required.
> 
> This patch modifies different data structures and APIs used
> in xenconsole to support two console types: PV and VCON (virtual console).
> 
> Change summary:
> 
> 1. Modify the domain structure to support two console types: PV and a
>    virtual console (VCON).
> 
> 2. Modify different APIs such as buffer_append() to take a new parameter
>    console_type as input and operate on the data structures indexed by
>    the console_type.
> 
> 3. Modfications in domain_create_ring():
>     - Bind to the vpl011 event channel obtained from the xen store as a
>       new
>       parameter
>     - Map the PFN to its address space to be used as IN/OUT ring
>       buffers.
>       It obtains the PFN from the xen store as a new parameter
> 
> 4. Modifications in handle_ring_read() to handle both PV and VCON
>    events.
> 
> 5. Add a new log_file for VCON console logs.
> 

It seems that this patch and previous one should be merged into one.

There are a lot of coding style issues, please fix all of them.

The code looks rather repetitive unfortunately. I believe a lot of the
repetitiveness can be avoided by using loops and pointers.

> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
>  tools/console/daemon/io.c | 508 ++++++++++++++++++++++++++++++++--------------
>  1 file changed, 356 insertions(+), 152 deletions(-)
> 
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index 0cd1fee..b9be5a5 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -164,11 +164,39 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
>  	return 0;
>  }
>  
> -static void buffer_append(struct domain *dom)
> +/*
> + * This function checks if the data is allowed to be buffered for that console.
> + * If not then it marks it pending for later receiving.
> + */
> +static bool buffer_available(struct domain *dom, int console_type)
> +{
> +	if (discard_overflowed_data ||
> +		!dom->buffer[console_type].max_capacity ||
> +		dom->buffer[console_type].size < dom->buffer[console_type].max_capacity)

Line too long.

> +	{
> +		dom->console_data_pending &= ~(1<<console_type);
> +		return true;
> +	}
> +	else
> +	{
> +		dom->console_data_pending |= (1<<console_type);
> +		return false;
> +	}
> +}
> +
> +static void buffer_append(struct domain *dom, int console_type)
>  {
> -	struct buffer *buffer = &dom->buffer;
> +	struct buffer *buffer = &dom->buffer[console_type];
> +	struct xencons_interface *intf=dom->interface[console_type];
> +	xenevtchn_port_or_error_t port=dom->local_port[console_type];

Spaces around "=".

> +
>  	XENCONS_RING_IDX cons, prod, size;
> -	struct xencons_interface *intf = dom->interface;
> +
> +	/*
> +	 * check if more data is allowed to be buffered
> +	 */
> +	if (!buffer_available(dom, console_type))
> +		return;
>  
>  	cons = intf->out_cons;
>  	prod = intf->out_prod;
> @@ -193,22 +221,22 @@ static void buffer_append(struct domain *dom)
>  
>  	xen_mb();
>  	intf->out_cons = cons;
> -	xenevtchn_notify(dom->xce_handle, dom->local_port);
> +	xenevtchn_notify(dom->xce_handle, port);
>  
>  	/* Get the data to the logfile as early as possible because if
>  	 * no one is listening on the console pty then it will fill up
>  	 * and handle_tty_write will stop being called.
>  	 */
> -	if (dom->log_fd != -1) {
> +	if (dom->log_fd[console_type] != -1) {
>  		int logret;
>  		if (log_time_guest) {
>  			logret = write_with_timestamp(
> -				dom->log_fd,
> +				dom->log_fd[console_type],
>  				buffer->data + buffer->size - size,
>  				size, &log_time_guest_needts);
>  		} else {
>  			logret = write_all(
> -				dom->log_fd,
> +				dom->log_fd[console_type],
>  				buffer->data + buffer->size - size,
>  				size);
>  		}
> @@ -296,12 +324,13 @@ static int create_hv_log(void)
>  	return fd;
>  }
>  
> -static int create_domain_log(struct domain *dom)
> +static int create_domain_log(struct domain *dom, int console_type)
>  {
>  	char logfile[PATH_MAX];
>  	char *namepath, *data, *s;
>  	int fd;
>  	unsigned int len;
> +	char *console_name[]={"pv", "vcon"};
>  
>  	namepath = xs_get_domain_path(xs, dom->domid);
>  	s = realloc(namepath, strlen(namepath) + 6);
> @@ -320,7 +349,7 @@ static int create_domain_log(struct domain *dom)
>  		return -1;
>  	}
>  
> -	snprintf(logfile, PATH_MAX-1, "%s/guest-%s.log", log_dir, data);
> +	snprintf(logfile, PATH_MAX-1, "%s/guest-%s-%s.log", log_dir, console_name[console_type], data);

Line too long.

>  	free(data);
>  	logfile[PATH_MAX-1] = '\0';
>  
> @@ -344,14 +373,24 @@ static int create_domain_log(struct domain *dom)
>  
>  static void domain_close_tty(struct domain *dom)
>  {
> -	if (dom->master_fd != -1) {
> -		close(dom->master_fd);
> -		dom->master_fd = -1;
> +	if (dom->master_fd[CONSOLE_TYPE_PV] != -1) {
> +		close(dom->master_fd[CONSOLE_TYPE_PV]);
> +		dom->master_fd[CONSOLE_TYPE_PV] = -1;
> +	}
> +
> +	if (dom->slave_fd[CONSOLE_TYPE_PV] != -1) {
> +		close(dom->slave_fd[CONSOLE_TYPE_PV]);
> +		dom->slave_fd[CONSOLE_TYPE_PV] = -1;
> +	}
> +
> +	if (dom->master_fd[CONSOLE_TYPE_VCON] != -1) {
> +		close(dom->master_fd[CONSOLE_TYPE_VCON]);
> +		dom->master_fd[CONSOLE_TYPE_VCON] = -1;
>  	}
>  
> -	if (dom->slave_fd != -1) {
> -		close(dom->slave_fd);
> -		dom->slave_fd = -1;
> +	if (dom->slave_fd[CONSOLE_TYPE_VCON] != -1) {
> +		close(dom->slave_fd[CONSOLE_TYPE_VCON]);
> +		dom->slave_fd[CONSOLE_TYPE_VCON] = -1;
>  	}

You can use two loops to avoid repetitive snippets. But I'm fine with
the code as-is, too.

>  }
>  
> @@ -424,63 +463,86 @@ static int domain_create_tty(struct domain *dom)
>  	char *data;
>  	unsigned int len;
>  	struct termios term;
> +	int console_type=0;
>  
> -	assert(dom->slave_fd == -1);
> -	assert(dom->master_fd == -1);
> +	assert(dom->master_fd[CONSOLE_TYPE_PV] == -1);
> +	assert(dom->slave_fd[CONSOLE_TYPE_PV] == -1);
> +	assert(dom->master_fd[CONSOLE_TYPE_VCON] == -1);
> +	assert(dom->slave_fd[CONSOLE_TYPE_VCON] == -1);
>  
> -	if (openpty(&dom->master_fd, &dom->slave_fd, NULL, NULL, NULL) < 0) {
> -		err = errno;
> -		dolog(LOG_ERR, "Failed to create tty for domain-%d "
> -		      "(errno = %i, %s)",
> -		      dom->domid, err, strerror(err));
> -		return 0;
> -	}
> +	/*
> +	 * Open pty for both PV and vcon consoles.
> +	 */
> +	for (console_type=0; console_type<MAX_CONSOLE; console_type++)

Spaces around "=" and "<".

> +	{
> +		if (openpty(&dom->master_fd[console_type], &dom->slave_fd[console_type], NULL, NULL, NULL) < 0) {

Line too long

> +			err = errno;
> +			dolog(LOG_ERR, "Failed to create tty for domain-%d "
> +				  "(errno = %i, %s)",
> +				  dom->domid, err, strerror(err));
> +			return 0;
> +		}
>  
> -	if (tcgetattr(dom->slave_fd, &term) < 0) {
> -		err = errno;
> -		dolog(LOG_ERR, "Failed to get tty attributes for domain-%d "
> -			"(errno = %i, %s)",
> -			dom->domid, err, strerror(err));
> -		goto out;
> -	}
> -	cfmakeraw(&term);
> -	if (tcsetattr(dom->slave_fd, TCSANOW, &term) < 0) {
> -		err = errno;
> -		dolog(LOG_ERR, "Failed to set tty attributes for domain-%d "
> -			"(errno = %i, %s)",
> -			dom->domid, err, strerror(err));
> -		goto out;
> -	}
> +		if (tcgetattr(dom->slave_fd[console_type], &term) < 0) {
> +			err = errno;
> +			dolog(LOG_ERR, "Failed to get tty attributes for domain-%d "
> +				"(errno = %i, %s)",
> +				dom->domid, err, strerror(err));
> +			goto out;
> +		}
> +		cfmakeraw(&term);
> +		if (tcsetattr(dom->slave_fd[console_type], TCSANOW, &term) < 0) {
> +			err = errno;
> +			dolog(LOG_ERR, "Failed to set tty attributes for domain-%d "
> +				"(errno = %i, %s)",
> +				dom->domid, err, strerror(err));
> +			goto out;
> +		}
>  
> -	if ((slave = ptsname(dom->master_fd)) == NULL) {
> -		err = errno;
> -		dolog(LOG_ERR, "Failed to get slave name for domain-%d "
> -		      "(errno = %i, %s)",
> -		      dom->domid, err, strerror(err));
> -		goto out;
> -	}
> +		if ((slave = ptsname(dom->master_fd[console_type])) == NULL) {
> +			err = errno;
> +			dolog(LOG_ERR, "Failed to get slave name for domain-%d "
> +				  "(errno = %i, %s)",
> +				  dom->domid, err, strerror(err));
> +			goto out;
> +		}
>  
> -	success = asprintf(&path, "%s/limit", dom->conspath) !=
> -		-1;
> -	if (!success)
> -		goto out;
> -	data = xs_read(xs, XBT_NULL, path, &len);
> -	if (data) {
> -		dom->buffer.max_capacity = strtoul(data, 0, 0);
> -		free(data);
> +		/*
> +		 * Initialize the console buffer capacity.
> +		 */
> +		success = asprintf(&path, "%s/limit", dom->conspath) !=
> +			-1;
> +		if (!success)
> +			goto out;
> +		data = xs_read(xs, XBT_NULL, path, &len);
> +		if (data) {
> +			dom->buffer[console_type].max_capacity = strtoul(data, 0, 0);
> +			free(data);
> +		}
> +		free(path);
> +
> +		/*
> +		 * Write console slave name to xen store.
> +		 */
> +		if (console_type == CONSOLE_TYPE_VCON)
> +			success = (asprintf(&path, "%s/vtty", dom->conspath) != -1);
> +		else
> +			success = (asprintf(&path, "%s/tty", dom->conspath) != -1);
> +
> +		if (!success)
> +			goto out;
> +		success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
> +		free(path);
> +
> +		if (fcntl(dom->master_fd[console_type], F_SETFL, O_NONBLOCK) == -1)
> +			goto out;
> +
> +		if (!dom->vcon_enabled)
> +			break;
>  	}
> -	free(path);
>  
> -	success = (asprintf(&path, "%s/tty", dom->conspath) != -1);
>  	if (!success)
>  		goto out;
> -	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
> -	free(path);
> -	if (!success)
> -		goto out;
> -
> -	if (fcntl(dom->master_fd, F_SETFL, O_NONBLOCK) == -1)
> -		goto out;
>  
>  	return 1;
>  out:
> @@ -523,21 +585,53 @@ static int xs_gather(struct xs_handle *xs, const char *dir, ...)
>  	return ret;
>  }
>  
> -static void domain_unmap_interface(struct domain *dom)
> +static void domain_unmap_interface(struct domain *dom, int console_type)
>  {
> -	if (dom->interface == NULL)
> +	if (dom->interface[console_type] == NULL)
>  		return;
> -	if (xgt_handle && dom->ring_ref == -1)
> -		xengnttab_unmap(xgt_handle, dom->interface, 1);
> +	if (xgt_handle && dom->ring_ref[console_type] == -1)
> +		xengnttab_unmap(xgt_handle, dom->interface[console_type], 1);
>  	else
> -		munmap(dom->interface, XC_PAGE_SIZE);
> -	dom->interface = NULL;
> -	dom->ring_ref = -1;
> +		munmap(dom->interface[console_type], XC_PAGE_SIZE);
> +	dom->interface[console_type] = NULL;
> +	dom->ring_ref[console_type] = -1;
> +}
> +
> +static int bind_event_channel(struct domain *dom, int new_rport, int *lport, int *rport)

Line too long.

> +{
> +	int err = 0, rc;
> +
> +	/* Go no further if port has not changed and we are still bound. */
> +	if (new_rport == *rport) {
> +		xc_evtchn_status_t status = {
> +		.dom = DOMID_SELF,
> +		.port = *lport };
> +		if ((xc_evtchn_status(xc, &status) == 0) &&
> +			(status.status == EVTCHNSTAT_interdomain))
> +			goto out;
> +	}
> +
> +	*lport = -1;
> +	*rport = -1;
> +	rc = xenevtchn_bind_interdomain(dom->xce_handle,
> +									dom->domid, new_rport);

Indentation.

> +
> +	if (rc == -1) {
> +		err = errno;
> +		xenevtchn_close(dom->xce_handle);
> +		dom->xce_handle = NULL;
> +		goto out;
> +	}
> +
> +	*lport = rc;
> +	*rport = new_rport;
> +out:
> +	return err;
>  }
>   
>  static int domain_create_ring(struct domain *dom)
>  {
> -	int err, remote_port, ring_ref, rc;
> +	int err, remote_port, ring_ref, vcon_remote_port, vcon_ring_ref;
>  	char *type, path[PATH_MAX];
>  
>  	err = xs_gather(xs, dom->conspath,
> @@ -547,6 +641,17 @@ static int domain_create_ring(struct domain *dom)
>  	if (err)
>  		goto out;
>  
> +	/* vcon console is optional. */
> +	err = xs_gather(xs, dom->conspath,
> +		"vcon-ring-ref", "%u", &vcon_ring_ref,
> +		"vcon-port", "%i", &vcon_remote_port,
> +		NULL);
> +

Indentation.

> +	if (err || vcon_ring_ref == -1)
> +		dom->vcon_enabled = false;
> +	else
> +		dom->vcon_enabled = true;
> +
>  	snprintf(path, sizeof(path), "%s/type", dom->conspath);
>  	type = xs_read(xs, XBT_NULL, path, NULL);
>  	if (type && strcmp(type, "xenconsoled") != 0) {
> @@ -556,41 +661,51 @@ static int domain_create_ring(struct domain *dom)
>  	free(type);
>  
>  	/* If using ring_ref and it has changed, remap */
> -	if (ring_ref != dom->ring_ref && dom->ring_ref != -1)
> -		domain_unmap_interface(dom);
> +	if (ring_ref != dom->ring_ref[CONSOLE_TYPE_PV] && dom->ring_ref[CONSOLE_TYPE_PV] != -1)

Line too long.

> +		domain_unmap_interface(dom, CONSOLE_TYPE_PV);
> +
> +	/* If using vcon ring_ref and it has changed, remap */
> +	if (dom->vcon_enabled &&
> +		vcon_ring_ref != dom->ring_ref[CONSOLE_TYPE_VCON] &&
> +		dom->ring_ref[CONSOLE_TYPE_VCON] != -1 )
> +		domain_unmap_interface(dom, CONSOLE_TYPE_VCON);

Indentation.

>  
> -	if (!dom->interface && xgt_handle) {
> +	if (!dom->interface[CONSOLE_TYPE_PV] && xgt_handle) {
>  		/* Prefer using grant table */
> -		dom->interface = xengnttab_map_grant_ref(xgt_handle,
> -			dom->domid, GNTTAB_RESERVED_CONSOLE,
> -			PROT_READ|PROT_WRITE);
> -		dom->ring_ref = -1;
> +		dom->interface[CONSOLE_TYPE_PV] = xengnttab_map_grant_ref(xgt_handle,
> +																  dom->domid, GNTTAB_RESERVED_CONSOLE,
> +																  PROT_READ|PROT_WRITE);
> +		dom->ring_ref[CONSOLE_TYPE_PV] = -1;

Indentation.

>  	}
> -	if (!dom->interface) {
> +
> +	if (!dom->interface[CONSOLE_TYPE_PV]) {
>  		/* Fall back to xc_map_foreign_range */
> -		dom->interface = xc_map_foreign_range(
> +		dom->interface[CONSOLE_TYPE_PV] = xc_map_foreign_range(
>  			xc, dom->domid, XC_PAGE_SIZE,
>  			PROT_READ|PROT_WRITE,
>  			(unsigned long)ring_ref);
> -		if (dom->interface == NULL) {
> +		if (dom->interface[CONSOLE_TYPE_PV] == NULL) {
>  			err = EINVAL;
>  			goto out;
>  		}
> -		dom->ring_ref = ring_ref;
> +		dom->ring_ref[CONSOLE_TYPE_PV] = ring_ref;
>  	}
>  
> -	/* Go no further if port has not changed and we are still bound. */
> -	if (remote_port == dom->remote_port) {
> -		xc_evtchn_status_t status = {
> -			.dom = DOMID_SELF,
> -			.port = dom->local_port };
> -		if ((xc_evtchn_status(xc, &status) == 0) &&
> -		    (status.status == EVTCHNSTAT_interdomain))
> +	/* Map vcon console ring buffer. */
> +	if (dom->vcon_enabled && !dom->interface[CONSOLE_TYPE_VCON]) {
> +
> +		/* Fall back to xc_map_foreign_range */
> +		dom->interface[CONSOLE_TYPE_VCON] = xc_map_foreign_range(
> +		xc, dom->domid, XC_PAGE_SIZE,
> +		PROT_READ|PROT_WRITE,
> +		(unsigned long)vcon_ring_ref);
> +		if ( dom->interface[CONSOLE_TYPE_VCON] == NULL ) {
> +			err = EINVAL;
>  			goto out;
> +		}
> +		dom->ring_ref[CONSOLE_TYPE_VCON] = vcon_ring_ref;
>  	}
>  
> -	dom->local_port = -1;
> -	dom->remote_port = -1;
>  	if (dom->xce_handle != NULL)
>  		xenevtchn_close(dom->xce_handle);
>  
> @@ -602,31 +717,46 @@ static int domain_create_ring(struct domain *dom)
>  		goto out;
>  	}
>   
> -	rc = xenevtchn_bind_interdomain(dom->xce_handle,
> -		dom->domid, remote_port);
> -
> -	if (rc == -1) {
> -		err = errno;
> +	err = bind_event_channel(dom, remote_port,
> +							 &dom->local_port[CONSOLE_TYPE_PV],
> +							 &dom->remote_port[CONSOLE_TYPE_PV]);

Indentation.

> +	if (err)
> +	{
>  		xenevtchn_close(dom->xce_handle);
> -		dom->xce_handle = NULL;
>  		goto out;
>  	}
> -	dom->local_port = rc;
> -	dom->remote_port = remote_port;
>  
> -	if (dom->master_fd == -1) {
> +	if (dom->vcon_enabled)
> +	{
> +		err = bind_event_channel(dom, vcon_remote_port,
> +								 &dom->local_port[CONSOLE_TYPE_VCON],
> +								 &dom->remote_port[CONSOLE_TYPE_VCON]);

Indentation.

> +		if (err)
> +		{
> +			xenevtchn_close(dom->xce_handle);
> +			goto out;
> +		}
> +	}
> +
> +	if (dom->master_fd[CONSOLE_TYPE_PV] == -1) {
>  		if (!domain_create_tty(dom)) {
>  			err = errno;
>  			xenevtchn_close(dom->xce_handle);
>  			dom->xce_handle = NULL;
> -			dom->local_port = -1;
> -			dom->remote_port = -1;
> +			dom->local_port[CONSOLE_TYPE_PV] = -1;
> +			dom->remote_port[CONSOLE_TYPE_PV] = -1;
> +			dom->local_port[CONSOLE_TYPE_VCON] = -1;
> +			dom->remote_port[CONSOLE_TYPE_VCON] = -1;
> +			dom->vcon_enabled = false;
>  			goto out;
>  		}
>  	}
>  
> -	if (log_guest && (dom->log_fd == -1))
> -		dom->log_fd = create_domain_log(dom);
> +	if (log_guest && (dom->log_fd[CONSOLE_TYPE_PV] == -1))
> +		dom->log_fd[CONSOLE_TYPE_PV] = create_domain_log(dom, CONSOLE_TYPE_PV);
> +
> +	if (log_guest && dom->vcon_enabled && (dom->log_fd[CONSOLE_TYPE_VCON] == -1))
> +		dom->log_fd[CONSOLE_TYPE_VCON] = create_domain_log(dom, CONSOLE_TYPE_VCON);
>  
>   out:
>  	return err;
> @@ -681,17 +811,24 @@ static struct domain *create_domain(int domid)
>  	dom->conspath = s;
>  	strcat(dom->conspath, "/console");
>  
> -	dom->master_fd = -1;
> -	dom->master_pollfd_idx = -1;
> -	dom->slave_fd = -1;
> -	dom->log_fd = -1;
> +	dom->master_fd[CONSOLE_TYPE_PV] = -1;
> +	dom->master_pollfd_idx[CONSOLE_TYPE_PV] = -1;
> +	dom->slave_fd[CONSOLE_TYPE_PV] = -1;
> +	dom->master_fd[CONSOLE_TYPE_VCON] = -1;
> +	dom->master_pollfd_idx[CONSOLE_TYPE_VCON] = -1;
> +	dom->slave_fd[CONSOLE_TYPE_VCON] = -1;
> +	dom->log_fd[CONSOLE_TYPE_PV] = -1;
> +	dom->log_fd[CONSOLE_TYPE_VCON] = -1;
>  	dom->xce_pollfd_idx = -1;
>  
>  	dom->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
>  
> -	dom->ring_ref = -1;
> -	dom->local_port = -1;
> -	dom->remote_port = -1;
> +	dom->ring_ref[CONSOLE_TYPE_PV] = -1;
> +	dom->ring_ref[CONSOLE_TYPE_VCON] = -1;
> +	dom->local_port[CONSOLE_TYPE_PV] = -1;
> +	dom->remote_port[CONSOLE_TYPE_PV] = -1;
> +	dom->local_port[CONSOLE_TYPE_VCON] = -1;
> +	dom->remote_port[CONSOLE_TYPE_VCON] = -1;
>  
>  	if (!watch_domain(dom, true))
>  		goto out;
> @@ -737,13 +874,21 @@ static void cleanup_domain(struct domain *d)
>  {
>  	domain_close_tty(d);
>  
> -	if (d->log_fd != -1) {
> -		close(d->log_fd);
> -		d->log_fd = -1;
> +	if (d->log_fd[CONSOLE_TYPE_PV] != -1) {
> +		close(d->log_fd[CONSOLE_TYPE_PV]);
> +		d->log_fd[CONSOLE_TYPE_PV] = -1;
> +	}
> +
> +	if (d->log_fd[CONSOLE_TYPE_VCON] != -1) {
> +		close(d->log_fd[CONSOLE_TYPE_VCON]);
> +		d->log_fd[CONSOLE_TYPE_VCON] = -1;
>  	}
>  
> -	free(d->buffer.data);
> -	d->buffer.data = NULL;
> +	free(d->buffer[CONSOLE_TYPE_PV].data);
> +	free(d->buffer[CONSOLE_TYPE_VCON].data);
> +
> +	d->buffer[CONSOLE_TYPE_PV].data = NULL;
> +	d->buffer[CONSOLE_TYPE_VCON].data = NULL;
>  
>  	free(d->conspath);
>  	d->conspath = NULL;
> @@ -755,7 +900,8 @@ static void shutdown_domain(struct domain *d)
>  {
>  	d->is_dead = true;
>  	watch_domain(d, false);
> -	domain_unmap_interface(d);
> +	domain_unmap_interface(d, CONSOLE_TYPE_PV);
> +	domain_unmap_interface(d, CONSOLE_TYPE_VCON);
>  	if (d->xce_handle != NULL)
>  		xenevtchn_close(d->xce_handle);
>  	d->xce_handle = NULL;
> @@ -786,9 +932,9 @@ static void enum_domains(void)
>  	}
>  }
>  
> -static int ring_free_bytes(struct domain *dom)
> +static int ring_free_bytes(struct domain *dom, int console_type)
>  {
> -	struct xencons_interface *intf = dom->interface;
> +	struct xencons_interface *intf = dom->interface[console_type];
>  	XENCONS_RING_IDX cons, prod, space;
>  
>  	cons = intf->in_cons;
> @@ -813,25 +959,26 @@ static void domain_handle_broken_tty(struct domain *dom, int recreate)
>  	}
>  }
>  
> -static void handle_tty_read(struct domain *dom)
> +static void handle_tty_read(struct domain *dom, int console_type)
>  {
>  	ssize_t len = 0;
>  	char msg[80];
>  	int i;
> -	struct xencons_interface *intf = dom->interface;
>  	XENCONS_RING_IDX prod;
> +	struct xencons_interface *intf=dom->interface[console_type];
> +	xenevtchn_port_or_error_t port=dom->local_port[console_type];
>  
>  	if (dom->is_dead)
>  		return;
>  
> -	len = ring_free_bytes(dom);
> +	len = ring_free_bytes(dom, console_type);
>  	if (len == 0)
>  		return;
>  
>  	if (len > sizeof(msg))
>  		len = sizeof(msg);
>  
> -	len = read(dom->master_fd, msg, len);
> +	len = read(dom->master_fd[console_type], msg, len);
>  	/*
>  	 * Note: on Solaris, len == 0 means the slave closed, and this
>  	 * is no problem, but Linux can't handle this usefully, so we
> @@ -847,28 +994,29 @@ static void handle_tty_read(struct domain *dom)
>  		}
>  		xen_wmb();
>  		intf->in_prod = prod;
> -		xenevtchn_notify(dom->xce_handle, dom->local_port);
> +		xenevtchn_notify(dom->xce_handle, port);
>  	} else {
>  		domain_close_tty(dom);
>  		shutdown_domain(dom);
>  	}
>  }
>  
> -static void handle_tty_write(struct domain *dom)
> +static void handle_tty_write(struct domain *dom, int console_type)
>  {
>  	ssize_t len;
>  
>  	if (dom->is_dead)
>  		return;
>  
> -	len = write(dom->master_fd, dom->buffer.data + dom->buffer.consumed,
> -		    dom->buffer.size - dom->buffer.consumed);
> +	len = write(dom->master_fd[console_type],
> +				dom->buffer[console_type].data + dom->buffer[console_type].consumed,
> +				dom->buffer[console_type].size - dom->buffer[console_type].consumed);
>   	if (len < 1) {
>  		dolog(LOG_DEBUG, "Write failed on domain %d: %zd, %d\n",
>  		      dom->domid, len, errno);
>  		domain_handle_broken_tty(dom, domain_is_valid(dom->domid));
>  	} else {
> -		buffer_advance(&dom->buffer, len);
> +		buffer_advance(&dom->buffer[console_type], len);
>  	}
>  }
>  
> @@ -884,7 +1032,10 @@ static void handle_ring_read(struct domain *dom)
>  
>  	dom->event_count++;
>  
> -	buffer_append(dom);
> +	if (port == dom->local_port[CONSOLE_TYPE_VCON])
> +		buffer_append(dom, CONSOLE_TYPE_VCON);
> +	else
> +		buffer_append(dom, CONSOLE_TYPE_PV);
>  
>  	if (dom->event_count < RATE_LIMIT_ALLOWANCE)
>  		(void)xenevtchn_unmask(dom->xce_handle, port);
> @@ -954,9 +1105,16 @@ static void handle_log_reload(void)
>  	if (log_guest) {
>  		struct domain *d;
>  		for (d = dom_head; d; d = d->next) {
> -			if (d->log_fd != -1)
> -				close(d->log_fd);
> -			d->log_fd = create_domain_log(d);
> +			if (d->log_fd[CONSOLE_TYPE_PV] != -1)
> +				close(d->log_fd[CONSOLE_TYPE_PV]);
> +			d->log_fd[CONSOLE_TYPE_PV] = create_domain_log(d, CONSOLE_TYPE_PV);
> +
> +			if (d->vcon_enabled)
> +			{
> +				if (d->log_fd[CONSOLE_TYPE_VCON] != -1)
> +					close(d->log_fd[CONSOLE_TYPE_VCON]);
> +				d->log_fd[CONSOLE_TYPE_PV] = create_domain_log(d, CONSOLE_TYPE_VCON);

Line too long.

> +			}
>  		}
>  	}
>  
> @@ -1074,7 +1232,9 @@ void handle_io(void)
>  			if ((now+5) > d->next_period) {
>  				d->next_period = now + RATE_LIMIT_PERIOD;
>  				if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
> -					(void)xenevtchn_unmask(d->xce_handle, d->local_port);
> +					(void)xenevtchn_unmask(d->xce_handle, d->local_port[CONSOLE_TYPE_PV]);
> +					if (d->vcon_enabled)
> +						(void)xenevtchn_unmask(d->xce_handle, d->local_port[CONSOLE_TYPE_VCON]);

Line too long.

>  				}
>  				d->event_count = 0;
>  			}
> @@ -1087,27 +1247,47 @@ void handle_io(void)
>  				    d->next_period < next_timeout)
>  					next_timeout = d->next_period;
>  			} else if (d->xce_handle != NULL) {
> -				if (discard_overflowed_data ||
> -				    !d->buffer.max_capacity ||
> -				    d->buffer.size < d->buffer.max_capacity) {
> +
> +				if (buffer_available(d, CONSOLE_TYPE_PV)) {
> +					int evtchn_fd = xenevtchn_fd(d->xce_handle);
> +					d->xce_pollfd_idx = set_fds(evtchn_fd,
> +												POLLIN|POLLPRI);

Indentation.

> +				}
> +
> +				if (buffer_available(d, CONSOLE_TYPE_VCON ) )

Extraneous space after CONSOLE_TYPE_VCON.

> +				{
>  					int evtchn_fd = xenevtchn_fd(d->xce_handle);
>  					d->xce_pollfd_idx = set_fds(evtchn_fd,
> -								    POLLIN|POLLPRI);
> +												POLLIN|POLLPRI);

Indentation.

>  				}
>  			}
>  
> -			if (d->master_fd != -1) {
> +			if (d->master_fd[CONSOLE_TYPE_PV] != -1) {
>  				short events = 0;
> -				if (!d->is_dead && ring_free_bytes(d))
> +				if (!d->is_dead && ring_free_bytes(d, CONSOLE_TYPE_PV))
>  					events |= POLLIN;
>  
> -				if (!buffer_empty(&d->buffer))
> +				if (!buffer_empty(&d->buffer[CONSOLE_TYPE_PV]))
>  					events |= POLLOUT;
>  
>  				if (events)
> -					d->master_pollfd_idx =
> -						set_fds(d->master_fd,
> -							events|POLLPRI);
> +					d->master_pollfd_idx[CONSOLE_TYPE_PV] =
> +						set_fds(d->master_fd[CONSOLE_TYPE_PV],
> +								events|POLLPRI);
> +			}
> +
> +			if (d->vcon_enabled && d->master_fd[CONSOLE_TYPE_VCON] != -1) {
> +				short events = 0;
> +				if (!d->is_dead && ring_free_bytes(d, CONSOLE_TYPE_VCON))
> +					events |= POLLIN;
> +
> +				if (!buffer_empty(&d->buffer[CONSOLE_TYPE_VCON]))
> +					events |= POLLOUT;
> +
> +				if (events)
> +					d->master_pollfd_idx[CONSOLE_TYPE_VCON] =
> +						set_fds(d->master_fd[CONSOLE_TYPE_VCON],
> +								events|POLLPRI);
>  			}
>  		}
>  
> @@ -1166,6 +1346,16 @@ void handle_io(void)
>  
>  		for (d = dom_head; d; d = n) {
>  			n = d->next;
> +
> +			/*
> +			 * Check if the data pending flag is set for any of the consoles.
> +			 * If yes then service those first.
> +			 */
> +			if ( d->console_data_pending & (1<<CONSOLE_TYPE_PV) )
> +				buffer_append(d, CONSOLE_TYPE_PV);
> +			else if ( d->console_data_pending & (1<<CONSOLE_TYPE_VCON) )
> +				buffer_append(d, CONSOLE_TYPE_VCON);
> +

Why? You seem to have skipped the ratelimit check here.

>  			if (d->event_count < RATE_LIMIT_ALLOWANCE) {
>  				if (d->xce_handle != NULL &&
>  				    d->xce_pollfd_idx != -1 &&
> @@ -1176,22 +1366,36 @@ void handle_io(void)
>  				    handle_ring_read(d);
>  			}
>  
> -			if (d->master_fd != -1 && d->master_pollfd_idx != -1) {
> -				if (fds[d->master_pollfd_idx].revents &
> +			if (d->master_fd[CONSOLE_TYPE_PV] != -1 && d->master_pollfd_idx[CONSOLE_TYPE_PV] != -1) {
> +				if (fds[d->master_pollfd_idx[CONSOLE_TYPE_PV]].revents &
> +				    ~(POLLIN|POLLOUT|POLLPRI))
> +					domain_handle_broken_tty(d, domain_is_valid(d->domid));
> +				else {
> +					if (fds[d->master_pollfd_idx[CONSOLE_TYPE_PV]].revents &
> +					    POLLIN)
> +						handle_tty_read(d, CONSOLE_TYPE_PV);
> +					if (fds[d->master_pollfd_idx[CONSOLE_TYPE_PV]].revents &
> +					    POLLOUT)
> +						handle_tty_write(d, CONSOLE_TYPE_PV);
> +				}
> +			}
> +
> +			if (d->master_fd[CONSOLE_TYPE_VCON] != -1 && d->master_pollfd_idx[CONSOLE_TYPE_VCON] != -1) {
> +				if (fds[d->master_pollfd_idx[CONSOLE_TYPE_VCON]].revents &
>  				    ~(POLLIN|POLLOUT|POLLPRI))
> -					domain_handle_broken_tty(d,
> -						   domain_is_valid(d->domid));
> +					domain_handle_broken_tty(d, domain_is_valid(d->domid));
>  				else {
> -					if (fds[d->master_pollfd_idx].revents &
> +					if (fds[d->master_pollfd_idx[CONSOLE_TYPE_VCON]].revents &
>  					    POLLIN)
> -						handle_tty_read(d);
> -					if (fds[d->master_pollfd_idx].revents &
> +						handle_tty_read(d, CONSOLE_TYPE_VCON);
> +					if (fds[d->master_pollfd_idx[CONSOLE_TYPE_VCON]].revents &
>  					    POLLOUT)
> -						handle_tty_write(d);
> +						handle_tty_write(d, CONSOLE_TYPE_VCON);
>  				}
>  			}
>  
> -			d->xce_pollfd_idx = d->master_pollfd_idx = -1;
> +			d->xce_pollfd_idx = d->master_pollfd_idx[CONSOLE_TYPE_PV] =
> +									d->master_pollfd_idx[CONSOLE_TYPE_VCON] = -1;
>  

Indentation and line too long.

>  			if (d->last_seen != enum_pass)
>  				shutdown_domain(d);
> -- 
> 2.7.4
> 

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

  reply	other threads:[~2017-04-12 16:33 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-03  9:44 [PATCH 00/10] pl011 emulation support in Xen Bhupinder Thakur
2017-04-03  9:44 ` [PATCH 01/10] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur
2017-04-12 16:32   ` Wei Liu
2017-04-19  0:15   ` Stefano Stabellini
2017-04-19  7:28     ` Bhupinder Thakur
2017-04-19  8:36       ` Julien Grall
2017-04-19 18:40       ` Stefano Stabellini
2017-04-25  7:31         ` Bhupinder Thakur
2017-04-25 17:56           ` Stefano Stabellini
2017-04-26  7:49             ` Bhupinder Thakur
2017-04-26  8:13               ` Julien Grall
2017-04-26 17:03                 ` Stefano Stabellini
2017-04-03  9:44 ` [PATCH 02/10] xen/arm: vpl011: Add new virtual console hvm params " Bhupinder Thakur
2017-04-19  0:22   ` Stefano Stabellini
2017-04-19  8:48     ` Bhupinder Thakur
2017-04-03  9:44 ` [PATCH 03/10] xen/arm: vpl011: Enable pl011 emulation for a guest domain " Bhupinder Thakur
2017-04-19  0:27   ` Stefano Stabellini
2017-04-03  9:44 ` [PATCH 04/10] xen/arm: vpl011: Provide a knob in libxl to enable/disable pl011 emulation Bhupinder Thakur
2017-04-12 16:32   ` Wei Liu
2017-04-13  8:19     ` Bhupinder Thakur
2017-04-13  8:37       ` Wei Liu
2017-04-19  0:29         ` Stefano Stabellini
2017-04-19  9:17           ` Bhupinder Thakur
2017-04-19 10:25             ` Wei Liu
2017-04-19 11:06               ` Julien Grall
2017-04-03  9:44 ` [PATCH 05/10] xen/arm: vpl011: Allocate a new PFN in the toolstack for the virtual console Bhupinder Thakur
2017-04-12 16:33   ` Wei Liu
2017-04-13  8:37     ` Bhupinder Thakur
2017-04-13  8:53       ` Wei Liu
2017-04-19  0:36         ` Stefano Stabellini
2017-04-19 10:28           ` Wei Liu
2017-04-19 11:01             ` Julien Grall
2017-04-19 13:05               ` Bhupinder Thakur
2017-04-19 13:35                 ` Julien Grall
2017-04-03  9:44 ` [PATCH 06/10] xen/arm: vpl011: Add new parameters to xenstore " Bhupinder Thakur
2017-04-12 16:32   ` Wei Liu
2017-04-25 10:18     ` Bhupinder Thakur
2017-04-25 11:55       ` Wei Liu
2017-04-19 18:58   ` Stefano Stabellini
2017-04-03  9:44 ` [PATCH 07/10] xen/arm: vpl011: Add a new console type to domain structure in xenconsole Bhupinder Thakur
2017-04-12 16:33   ` Wei Liu
2017-04-13  9:49     ` Bhupinder Thakur
2017-04-19 19:09   ` Stefano Stabellini
2017-04-03  9:44 ` [PATCH 08/10] xen/arm: vpl011: Modify the APIs in xenconsole to acces both PV and VCON consoles Bhupinder Thakur
2017-04-12 16:33   ` Wei Liu [this message]
2017-04-24 14:52     ` Bhupinder Thakur
2017-04-03  9:44 ` [PATCH 09/10] xen/arm: vpl011: Add new virtual console to xenconsole client Bhupinder Thakur
2017-04-19 18:55   ` Stefano Stabellini
2017-04-03  9:44 ` [PATCH 10/10] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
2017-04-19 18:53   ` Stefano Stabellini
2017-04-20 12:47 ` [PATCH 00/10] pl011 emulation support in Xen Julien Grall
2017-04-26 15:21   ` Bhupinder Thakur
2017-04-26 17:09     ` Stefano Stabellini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170412163315.ns7kqxvesrxei5ev@citrix.com \
    --to=wei.liu2@citrix.com \
    --cc=bhupinder.thakur@linaro.org \
    --cc=ian.jackson@eu.citrix.com \
    --cc=julien.grall@arm.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.