xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/14 v4] PL011 emulation support in Xen
@ 2017-06-06 17:25 Bhupinder Thakur
  2017-06-06 17:25 ` [PATCH 01/14 v4] xen/arm: vpl011: Move vgic register access functions to vreg.h Bhupinder Thakur
                   ` (14 more replies)
  0 siblings, 15 replies; 65+ messages in thread
From: Bhupinder Thakur @ 2017-06-06 17:25 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

PL011 emulation for guests in Xen
===================================
Linaro has published VM System specification for ARM Processors, which
provides a set of guidelines for both guest OS and hypervisor implementations, 
such that building OS images according to these guidelines guarantees
that those images can also run on hypervisors compliant with this specification.

One of the spec requirements is that the hypervisor must provide an
emulated PL011 UART as a serial console which meets the minimum requirements in 
SBSA UART as defined in appendix B of the following 
ARM Server Base Architecture Document:

https://static.docs.arm.com/den0029/a/Server_Base_System_Architecture_v3_1_ARM_DEN_0029A.pdf.

This feature allows the Xen guests to use SBSA compliant pl011 UART as 
as a console. 

Note that SBSA pl011 UART is a subset of full featured ARM pl011 UART and
supports only a subset of registers as mentioned below. It does not support
rx/tx DMA.

Currently, Xen supports paravirtualized (aka PV console) and an emulated serial 
consoles. This feature will expose an emulated SBSA pl011 UART console to the
guest, which a user can access using xenconsole.

The device tree passed to the guest VM will contain the pl011 MMIO address 
range and an irq for receiving rx/tx pl011 interrupts. The device tree format 
is specified in Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt.

The Xen hypervisor will expose two types of interfaces to the backend and domU. 

The interface exposed to domU will be an emulated pl011 UART by emulating the 
access to the following pl011 registers by the guest.

- Data register (DR)            - RW
- Raw interrupt status register (RIS)   - RO
- Masked interrupt status register (MIS)- RO
- Interrupt Mask (IMSC)         - RW
- Interrupt Clear (ICR)         - WO

It will also inject the pl011 interrupts to the guest in the following 
conditions:

- incoming data in the rx buffer for the guest
- there is space in the tx buffer for the guest to write more data

The interface exposed to the backend will be the same PV console interface, 
which minimizes the changes required in xenconsole to support a new pl011 console.

This interface has rx and tx ring buffers and an event channel for 
sending/receiving events from the backend. 

So essentially Xen handles the data on behalf of domU and the backend. Any data 
written by domU is captured by Xen and written to the TX (OUT) ring buffer 
and a pl011 event is raised to the backend to read the TX ring buffer.
 
Similarly on reciving a pl011 event, Xen injects an interrupt to guest to
indicate there is data available in the RX (IN) ring buffer.

The pl011 UART state is completely captured in the set of registers 
mentioned above and this state is updated everytime there is an event from 
the backend or there is register read/write access from domU. 

For example, if domU has masked the rx interrupt in the IMSC register, then Xen 
will not inject an interrupt to guest and will just update the RIS register. 
Once the interrupt is unmasked by guest, the interrupt will be delivered to the 
guest.

Changes summary:

Xen Hypervisor
===============

1. Add emulation code to emulate read/write access to pl011 registers and pl011 
   interrupts:
    - It emulates DR read/write by reading and writing from/to the IN and 
      OUT ring buffers and raising an event to dom0 when there is data in 
      the OUT ring buffer and injecting an interrupt to the guest when there 
      is data in the IN ring buffer.
    - Other registers are related to interrupt management and essentially 
      control when interrupts are delivered to the guest.

2. Add a new domctl API to initialize vpl011 emulation in Xen.

3. Enable vpl011 emulation for a domain based on a libxl option passed during 
   domain creation.

Toolstack
==========

1. Add a new option "vuart" in the domU configuration file to enable/disable vuart.

2. Create a SBSA UART DT node in the guest device tree. It uses a fixed
   vpl011 SPI IRQ number and MMIO address.

3. Call vpl011 init DOMCTL API to enable vpl011 emulation.

5. Add a new vuart xenstore node, which contains:
    - ring-ref
    - event channel
    - buffer limit
    - type

Xenconsoled
============

1. Split the domain structure to support multiple consoles.

2. Modify different APIs such as buffer_append() etc. to operate on the 
   console structure.
   
3. Add support for handling multiple consoles.

4. Add support for vuart console:

The vpl011 changes available at the following repo:

url: ssh://git@git.linaro.org:/people/bhupinder.thakur/xen.git
branch: vpl011_v4

There are some TBD items which need to be looked at in the future:

1. Currently UEFI firmware logs the output to hvc console only. How can 
   UEFI firmware be made aware of pl011 console and how it can use it
   as a console instead of hvc.
2. Linux seems to have hvc console as the default console i.e. if no
   console is specified then it uses hvc as the console. How can an 
   option be provided in Linux to select either hvc or pl011 as the 
   default console.

3. ACPI support for pl011 device.

CC: ij
CC: wl
CC: ss
CC: jg
CC: kw

Bhupinder Thakur (14):
  xen/arm: vpl011: Move vgic register access functions to vreg.h
  xen/arm: vpl011: Define generic vreg_reg* access functions in vreg.h
  xen/arm: vpl011: Add pl011 uart emulation in Xen
  xen/arm: vpl011: Add support for vuart in libxl
  xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart
  xen/arm: vpl011: Add a new domctl API to initialize vpl011
  xen/arm: vpl011: Add a new vuart node in the xenstore
  xen/arm: vpl011: Modify xenconsole to define and use a new console    
    structure
  xen/arm: vpl011: Modify xenconsole functions to take console structure
    as input
  xen/arm: vpl011: Modify xenconsole to support multiple consoles
  xen/arm: vpl011: Add support for vuart console in xenconsole
  xen/arm: vpl011: Add a new vuart console type to xenconsole client
  xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree
  xen/arm: vpl011: Update documentation for vuart console support

 config/arm32.mk                      |   1 +
 config/arm64.mk                      |   1 +
 docs/man/xl.cfg.pod.5.in             |   9 +
 docs/misc/console.txt                |  44 ++-
 tools/console/Makefile               |   4 +-
 tools/console/client/main.c          |  25 +-
 tools/console/daemon/io.c            | 544 ++++++++++++++++++++++++-----------
 tools/libxc/include/xc_dom.h         |   3 +
 tools/libxc/include/xenctrl.h        |  17 ++
 tools/libxc/xc_dom_arm.c             |  12 +-
 tools/libxc/xc_dom_boot.c            |   2 +
 tools/libxc/xc_domain.c              |  23 ++
 tools/libxl/libxl.h                  |   6 +
 tools/libxl/libxl_arch.h             |   7 +
 tools/libxl/libxl_arm.c              |  71 ++++-
 tools/libxl/libxl_console.c          |  47 +++
 tools/libxl/libxl_create.c           |  12 +-
 tools/libxl/libxl_device.c           |   9 +-
 tools/libxl/libxl_dom.c              |   8 +-
 tools/libxl/libxl_internal.h         |   7 +
 tools/libxl/libxl_types.idl          |   7 +
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_x86.c              |   8 +
 tools/xl/Makefile                    |   4 +
 tools/xl/xl_cmdtable.c               |   4 +
 tools/xl/xl_console.c                |  11 +-
 tools/xl/xl_parse.c                  |   8 +
 xen/arch/arm/Kconfig                 |   5 +
 xen/arch/arm/Makefile                |   1 +
 xen/arch/arm/domain.c                |   2 +
 xen/arch/arm/domctl.c                |  44 ++-
 xen/arch/arm/vgic-v2.c               |  28 +-
 xen/arch/arm/vgic-v3.c               |  40 +--
 xen/arch/arm/vpl011.c                | 418 +++++++++++++++++++++++++++
 xen/include/asm-arm/domain.h         |   6 +
 xen/include/asm-arm/pl011-uart.h     |   2 +
 xen/include/asm-arm/vgic.h           | 111 +------
 xen/include/asm-arm/vpl011.h         |  74 +++++
 xen/include/asm-arm/vreg.h           | 109 +++++++
 xen/include/public/arch-arm.h        |   6 +
 xen/include/public/domctl.h          |  12 +
 xen/include/public/io/console.h      |   4 +
 42 files changed, 1421 insertions(+), 336 deletions(-)
 create mode 100644 xen/arch/arm/vpl011.c
 create mode 100644 xen/include/asm-arm/vpl011.h

-- 
2.7.4


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

^ permalink raw reply	[flat|nested] 65+ messages in thread
* [PATCH 10/14 v4] xen/arm: vpl011: Modify xenconsole to support multiple consoles
@ 2017-06-06 10:04 Bhupinder Thakur
  0 siblings, 0 replies; 65+ messages in thread
From: Bhupinder Thakur @ 2017-06-06 10:04 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

This patch adds the support for multiple consoles and introduces the iterator
functions to operate on multiple consoles.

This patch is in preparation to support a new vuart console.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---

Changes since v3:
- The changes in xenconsole have been split into four patches. This is the third patch.

 tools/console/daemon/io.c | 364 +++++++++++++++++++++++++++++++++-------------
 1 file changed, 263 insertions(+), 101 deletions(-)

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index c5dd08d..db73e10 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -90,12 +90,15 @@ struct buffer {
 };
 
 struct console {
+	char *xsname;
+	char *ttyname;
 	int master_fd;
 	int master_pollfd_idx;
 	int slave_fd;
 	int log_fd;
 	struct buffer buffer;
-	char *conspath;
+	char *xspath;
+	char *log_suffix;
 	int ring_ref;
 	xenevtchn_port_or_error_t local_port;
 	xenevtchn_port_or_error_t remote_port;
@@ -103,6 +106,23 @@ struct console {
 	struct domain *d;
 };
 
+struct console_data {
+	char *xsname;
+	char *ttyname;
+	char *log_suffix;
+};
+
+static struct console_data console_data[] = {
+
+	{
+		.xsname = "/console",
+		.ttyname = "tty",
+		.log_suffix = "",
+	},
+};
+
+#define MAX_CONSOLE (sizeof(console_data)/sizeof(struct console_data))
+
 struct domain {
 	int domid;
 	bool is_dead;
@@ -112,11 +132,90 @@ struct domain {
 	int xce_pollfd_idx;
 	int event_count;
 	long long next_period;
-	struct console console;
+	struct console console[MAX_CONSOLE];
 };
 
 static struct domain *dom_head;
 
+typedef void (*VOID_ITER_FUNC_ARG1)(struct console *);
+typedef bool (*BOOL_ITER_FUNC_ARG1)(struct console *);
+typedef int (*INT_ITER_FUNC_ARG1)(struct console *);
+typedef void (*VOID_ITER_FUNC_ARG2)(struct console *,  unsigned int);
+typedef int (*INT_ITER_FUNC_ARG3)(struct console *,
+			 struct domain *dom, void **);
+
+static inline bool console_enabled(struct console *con)
+{
+	return con->local_port != -1;
+}
+
+static inline void console_iter_void_arg1(struct domain *d,
+										  VOID_ITER_FUNC_ARG1 iter_func)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		iter_func(con);
+	}
+}
+
+static inline void console_iter_void_arg2(struct domain *d,
+										  VOID_ITER_FUNC_ARG2 iter_func,
+										  unsigned int iter_data)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		iter_func(con, iter_data);
+	}
+}
+
+static inline bool console_iter_bool_arg1(struct domain *d,
+										  BOOL_ITER_FUNC_ARG1 iter_func)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		if (iter_func(con))
+			return true;
+	}
+	return false;
+}
+
+static inline int console_iter_int_arg1(struct domain *d,
+										INT_ITER_FUNC_ARG1 iter_func)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		if (iter_func(con))
+			return 1;
+	}
+	return 0;
+}
+
+static inline int console_iter_int_arg3(struct domain *d,
+										INT_ITER_FUNC_ARG3 iter_func,
+										void *iter_data)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		if (iter_func(con, d, iter_data))
+			return 1;
+	}
+	return 0;
+}
 static int write_all(int fd, const char* buf, size_t len)
 {
 	while (len) {
@@ -163,12 +262,27 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
 	return 0;
 }
 
-static void buffer_append(struct console *con)
+static inline bool buffer_available(struct console *con)
+{
+	if (discard_overflowed_data ||
+		!con->buffer.max_capacity ||
+		con->buffer.size < con->buffer.max_capacity)
+		return true;
+	else
+		return false;
+}
+
+static void buffer_append(struct console *con, unsigned int data)
 {
 	struct buffer *buffer = &con->buffer;
+	struct xencons_interface *intf = con->interface;
+	xenevtchn_port_or_error_t rxport = (xenevtchn_port_or_error_t)data;
 	struct domain *dom = con->d;
 	XENCONS_RING_IDX cons, prod, size;
-	struct xencons_interface *intf = con->interface;
+
+	/* If incoming data is not for the current console then ignore. */
+	if (con->local_port != rxport)
+		return;
 
 	cons = intf->out_cons;
 	prod = intf->out_prod;
@@ -321,7 +435,7 @@ static int create_console_log(struct console *con)
 		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, data, con->log_suffix);
 	free(data);
 	logfile[PATH_MAX-1] = '\0';
 
@@ -427,6 +541,9 @@ static int console_create_tty(struct console *con)
 	struct termios term;
 	struct domain *dom = con->d;
 
+	if (!console_enabled(con))
+		return 1;
+
 	assert(con->slave_fd == -1);
 	assert(con->master_fd == -1);
 
@@ -462,7 +579,7 @@ static int console_create_tty(struct console *con)
 		goto out;
 	}
 
-	success = asprintf(&path, "%s/limit", con->conspath) !=
+	success = asprintf(&path, "%s/limit", con->xspath) !=
 		-1;
 	if (!success)
 		goto out;
@@ -473,7 +590,7 @@ static int console_create_tty(struct console *con)
 	}
 	free(path);
 
-	success = (asprintf(&path, "%s/tty", con->conspath) != -1);
+	success = (asprintf(&path, "%s/%s", con->xspath, con->ttyname) != -1);
 	if (!success)
 		goto out;
 	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
@@ -543,14 +660,14 @@ static int console_create_ring(struct console *con)
 	char *type, path[PATH_MAX];
 	struct domain *dom = con->d;
 
-	err = xs_gather(xs, con->conspath,
+	err = xs_gather(xs, con->xspath,
 			"ring-ref", "%u", &ring_ref,
 			"port", "%i", &remote_port,
 			NULL);
 	if (err)
 		goto out;
 
-	snprintf(path, sizeof(path), "%s/type", con->conspath);
+	snprintf(path, sizeof(path), "%s/type", con->xspath);
 	type = xs_read(xs, XBT_NULL, path, NULL);
 	if (type && strcmp(type, "xenconsoled") != 0) {
 		free(type);
@@ -594,15 +711,16 @@ static int console_create_ring(struct console *con)
 
 	con->local_port = -1;
 	con->remote_port = -1;
-	if (dom->xce_handle != NULL)
-		xenevtchn_close(dom->xce_handle);
 
-	/* Opening evtchn independently for each console is a bit
-	 * wasteful, but that's how the code is structured... */
-	dom->xce_handle = xenevtchn_open(NULL, 0);
-	if (dom->xce_handle == NULL) {
-		err = errno;
-		goto out;
+	if (dom->xce_handle == NULL)
+	{
+		/* Opening evtchn independently for each console is a bit
+		 * wasteful, but that's how the code is structured... */
+		dom->xce_handle = xenevtchn_open(NULL, 0);
+		if (dom->xce_handle == NULL) {
+			err = errno;
+			goto out;
+		}
 	}
  
 	rc = xenevtchn_bind_interdomain(dom->xce_handle,
@@ -639,29 +757,65 @@ static bool watch_domain(struct domain *dom, bool watch)
 {
 	char domid_str[3 + MAX_STRLEN(dom->domid)];
 	bool success;
-	struct console *con = &dom->console;
+	struct console *con = &dom->console[0];
 
 	snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid);
 	if (watch) {
-		success = xs_watch(xs, con->conspath, domid_str);
+		success = xs_watch(xs, con->xspath, domid_str);
 		if (success)
-			console_create_ring(con);
+			console_iter_int_arg1(dom, console_create_ring);
 		else
-			xs_unwatch(xs, con->conspath, domid_str);
+			xs_unwatch(xs, con->xspath, domid_str);
 	} else {
-		success = xs_unwatch(xs, con->conspath, domid_str);
+		success = xs_unwatch(xs, con->xspath, domid_str);
 	}
 
 	return success;
 }
 
+static int console_init(struct console *con, struct domain *dom, void **data)
+{
+	char *s;
+	int err = -1;
+	struct console_data **con_data = (struct console_data **)data;
+
+	con->master_fd = -1;
+	con->master_pollfd_idx = -1;
+	con->slave_fd = -1;
+	con->log_fd = -1;
+	con->ring_ref = -1;
+	con->local_port = -1;
+	con->remote_port = -1;
+	con->d = dom;
+	con->ttyname = (*con_data)->ttyname;
+	con->log_suffix = (*con_data)->log_suffix;
+	con->xsname = (*con_data)->xsname;
+	con->xspath = xs_get_domain_path(xs, dom->domid);
+	s = realloc(con->xspath, strlen(con->xspath) +
+				strlen(con->xsname) + 1);
+	if (s)
+	{
+		con->xspath = s;
+		strcat(con->xspath, con->xsname);
+		err = 0;
+	}
+
+	(*con_data)++;
+
+	return err;
+}
+
+static void console_free(struct console *con)
+{
+	if (con->xspath)
+		free(con->xspath);
+}
 
 static struct domain *create_domain(int domid)
 {
 	struct domain *dom;
-	char *s;
 	struct timespec ts;
-	struct console *con;
+	struct console_data *con_data = &console_data[0];
 
 	if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
 		dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
@@ -678,28 +832,13 @@ static struct domain *create_domain(int domid)
 
 	dom->domid = domid;
 
-	con = &dom->console;
-	con->conspath = xs_get_domain_path(xs, dom->domid);
-	s = realloc(con->conspath, strlen(con->conspath) +
-		    strlen("/console") + 1);
-	if (s == NULL)
+	if (console_iter_int_arg3(dom, console_init, (void **)&con_data))
 		goto out;
-	con->conspath = s;
-	strcat(con->conspath, "/console");
 
-	con->master_fd = -1;
-	con->master_pollfd_idx = -1;
-	con->slave_fd = -1;
-	con->log_fd = -1;
-	con->d = dom;
 	dom->xce_pollfd_idx = -1;
 
 	dom->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
 
-	con->ring_ref = -1;
-	con->local_port = -1;
-	con->remote_port = -1;
-
 	if (!watch_domain(dom, true))
 		goto out;
 
@@ -710,7 +849,7 @@ static struct domain *create_domain(int domid)
 
 	return dom;
  out:
-	free(con->conspath);
+	console_iter_void_arg1(dom, console_free);
 	free(dom);
 	return NULL;
 }
@@ -740,33 +879,40 @@ static void remove_domain(struct domain *dom)
 	}
 }
 
-static void cleanup_domain(struct domain *d)
+static void console_cleanup(struct console *con)
 {
-	struct console *con = &d->console;
-
-	console_close_tty(con);
-
 	if (con->log_fd != -1) {
 		close(con->log_fd);
 		con->log_fd = -1;
 	}
 
-	free(con->buffer.data);
-	con->buffer.data = NULL;
+	if (con->buffer.data)
+	{
+		free(con->buffer.data);
+		con->buffer.data = NULL;
+	}
 
-	free(con->conspath);
-	con->conspath = NULL;
+	if (con->xspath)
+	{
+		free(con->xspath);
+		con->xspath = NULL;
+	}
+}
+
+static void cleanup_domain(struct domain *d)
+{
+	console_iter_void_arg1(d, console_close_tty);
+
+	console_iter_void_arg1(d, console_cleanup);
 
 	remove_domain(d);
 }
 
 static void shutdown_domain(struct domain *d)
 {
-	struct console *con = &d->console;
-
 	d->is_dead = true;
 	watch_domain(d, false);
-	console_unmap_interface(con);
+	console_iter_void_arg1(d, console_unmap_interface);
 	if (d->xce_handle != NULL)
 		xenevtchn_close(d->xce_handle);
 	d->xce_handle = NULL;
@@ -885,10 +1031,15 @@ static void handle_tty_write(struct console *con)
 	}
 }
 
+static void console_event_unmask(struct console *con)
+{
+	if (con->local_port != -1)
+		(void)xenevtchn_unmask(con->d->xce_handle, con->local_port);
+}
+
 static void handle_ring_read(struct domain *dom)
 {
 	xenevtchn_port_or_error_t port;
-	struct console *con = &dom->console;
 
 	if (dom->is_dead)
 		return;
@@ -898,10 +1049,10 @@ static void handle_ring_read(struct domain *dom)
 
 	dom->event_count++;
 
-	buffer_append(con);
+	console_iter_void_arg2(dom, buffer_append, port);
 
 	if (dom->event_count < RATE_LIMIT_ALLOWANCE)
-		(void)xenevtchn_unmask(dom->xce_handle, port);
+		console_iter_void_arg1(dom, console_event_unmask);
 }
 
 static void handle_xs(void)
@@ -922,7 +1073,7 @@ static void handle_xs(void)
 		/* We may get watches firing for domains that have recently
 		   been removed, so dom may be NULL here. */
 		if (dom && dom->is_dead == false)
-			console_create_ring(&dom->console);
+			console_iter_int_arg1(dom, console_create_ring);
 	}
 
 	free(vec);
@@ -963,16 +1114,22 @@ static void handle_hv_logs(xenevtchn_handle *xce_handle, bool force)
 		(void)xenevtchn_unmask(xce_handle, port);
 }
 
+static void console_open_log(struct console *con)
+{
+	if (console_enabled(con))
+	{
+		if (con->log_fd != -1)
+			close(con->log_fd);
+		con->log_fd = create_console_log(con);
+	}
+}
+
 static void handle_log_reload(void)
 {
 	if (log_guest) {
 		struct domain *d;
 		for (d = dom_head; d; d = d->next) {
-			struct console *con = &d->console;
-
-			if (con->log_fd != -1)
-				close(con->log_fd);
-			con->log_fd = create_console_log(con);
+			console_iter_void_arg1(d, console_open_log);
 		}
 	}
 
@@ -1024,6 +1181,40 @@ static void reset_fds(void)
 		memset(fds, 0, sizeof(struct pollfd) * current_array_size);
 }
 
+static void add_console_fd(struct console *con)
+{
+	if (con->master_fd != -1) {
+		short events = 0;
+		if (!con->d->is_dead && ring_free_bytes(con))
+			events |= POLLIN;
+
+		if (!buffer_empty(&con->buffer))
+			events |= POLLOUT;
+
+		if (events)
+			con->master_pollfd_idx =
+				set_fds(con->master_fd, events|POLLPRI);
+	}
+}
+
+static void process_console(struct console *con)
+{
+	if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
+		if (fds[con->master_pollfd_idx].revents &
+			~(POLLIN|POLLOUT|POLLPRI))
+			console_handle_broken_tty(con, domain_is_valid(con->d->domid));
+		else {
+			if (fds[con->master_pollfd_idx].revents &
+				POLLIN)
+				handle_tty_read(con);
+			if (fds[con->master_pollfd_idx].revents &
+				POLLOUT)
+				handle_tty_write(con);
+		}
+	}
+	con->master_pollfd_idx = -1;
+}
+
 void handle_io(void)
 {
 	int ret;
@@ -1081,7 +1272,6 @@ void handle_io(void)
 		/* Re-calculate any event counter allowances & unblock
 		   domains with new allowance */
 		for (d = dom_head; d; d = d->next) {
-			struct console *con = &d->console;
 
 			/* CS 16257:955ee4fa1345 introduces a 5ms fuzz
 			 * for select(), it is not clear poll() has
@@ -1092,14 +1282,13 @@ 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, con->local_port);
+					console_iter_void_arg1(d, console_event_unmask);
 				}
 				d->event_count = 0;
 			}
 		}
 
 		for (d = dom_head; d; d = d->next) {
-			struct console *con = &d->console;
 
 			if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
 				/* Determine if we're going to be the next time slice to expire */
@@ -1107,28 +1296,15 @@ void handle_io(void)
 				    d->next_period < next_timeout)
 					next_timeout = d->next_period;
 			} else if (d->xce_handle != NULL) {
-				if (discard_overflowed_data ||
-				    !con->buffer.max_capacity ||
-				    con->buffer.size < con->buffer.max_capacity) {
-					int evtchn_fd = xenevtchn_fd(d->xce_handle);
-					d->xce_pollfd_idx = set_fds(evtchn_fd,
-								    POLLIN|POLLPRI);
+					if (console_iter_bool_arg1(d, buffer_available))
+					{
+						int evtchn_fd = xenevtchn_fd(d->xce_handle);
+						d->xce_pollfd_idx = set_fds(evtchn_fd,
+													POLLIN|POLLPRI);
+					}
 				}
-			}
-
-			if (con->master_fd != -1) {
-				short events = 0;
-				if (!d->is_dead && ring_free_bytes(con))
-					events |= POLLIN;
 
-				if (!buffer_empty(&con->buffer))
-					events |= POLLOUT;
-
-				if (events)
-					con->master_pollfd_idx =
-						set_fds(con->master_fd,
-							events|POLLPRI);
-			}
+			console_iter_void_arg1(d, add_console_fd);
 		}
 
 		/* If any domain has been rate limited, we need to work
@@ -1185,7 +1361,6 @@ void handle_io(void)
 		}
 
 		for (d = dom_head; d; d = n) {
-			struct console *con = &d->console;
 
 			n = d->next;
 			if (d->event_count < RATE_LIMIT_ALLOWANCE) {
@@ -1198,22 +1373,9 @@ void handle_io(void)
 				    handle_ring_read(d);
 			}
 
-			if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
-				if (fds[con->master_pollfd_idx].revents &
-				    ~(POLLIN|POLLOUT|POLLPRI))
-					console_handle_broken_tty(con,
-						   domain_is_valid(d->domid));
-				else {
-					if (fds[con->master_pollfd_idx].revents &
-					    POLLIN)
-						handle_tty_read(con);
-					if (fds[con->master_pollfd_idx].revents &
-					    POLLOUT)
-						handle_tty_write(con);
-				}
-			}
+			console_iter_void_arg1(d, process_console);
 
-			d->xce_pollfd_idx = con->master_pollfd_idx = -1;
+			d->xce_pollfd_idx = -1;
 
 			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

^ permalink raw reply related	[flat|nested] 65+ messages in thread

end of thread, other threads:[~2017-06-23 12:45 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-06 17:25 [PATCH 00/14 v4] PL011 emulation support in Xen Bhupinder Thakur
2017-06-06 17:25 ` [PATCH 01/14 v4] xen/arm: vpl011: Move vgic register access functions to vreg.h Bhupinder Thakur
2017-06-09 12:49   ` Julien Grall
2017-06-06 17:25 ` [PATCH 02/14 v4] xen/arm: vpl011: Define generic vreg_reg* access functions in vreg.h Bhupinder Thakur
2017-06-09 12:54   ` Julien Grall
2017-06-19  9:33   ` Andre Przywara
2017-06-19 16:53     ` Bhupinder Thakur
2017-06-19 16:59       ` Andre Przywara
2017-06-06 17:25 ` [PATCH 03/14 v4] xen/arm: vpl011: Add pl011 uart emulation in Xen Bhupinder Thakur
2017-06-06 23:02   ` Stefano Stabellini
2017-06-09 13:15     ` Julien Grall
2017-06-09 18:02       ` Stefano Stabellini
2017-06-13  8:58       ` Bhupinder Thakur
2017-06-13  9:25         ` Julien Grall
2017-06-09 13:54   ` Julien Grall
2017-06-13 10:57     ` Bhupinder Thakur
2017-06-13 12:44       ` Julien Grall
2017-06-13 17:50         ` Stefano Stabellini
2017-06-14  5:47         ` Bhupinder Thakur
2017-06-14  9:33           ` Julien Grall
2017-06-19 10:14   ` Andre Przywara
2017-06-22  5:16     ` Bhupinder Thakur
2017-06-23 12:45     ` Julien Grall
2017-06-06 17:25 ` [PATCH 04/14 v4] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
2017-06-06 23:07   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 05/14 v4] xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart Bhupinder Thakur
2017-06-06 23:17   ` Stefano Stabellini
2017-06-07 16:43   ` Wei Liu
2017-06-06 17:25 ` [PATCH 06/14 v4] xen/arm: vpl011: Add a new domctl API to initialize vpl011 Bhupinder Thakur
2017-06-06 23:26   ` Stefano Stabellini
2017-06-09 14:06     ` Julien Grall
2017-06-09 18:32       ` Stefano Stabellini
2017-06-14  7:35     ` Bhupinder Thakur
2017-06-14  8:34       ` Bhupinder Thakur
2017-06-09 14:13   ` Julien Grall
2017-06-14  9:16     ` Bhupinder Thakur
2017-06-14 10:15       ` Julien Grall
2017-06-15  6:33         ` Bhupinder Thakur
2017-06-19 10:59           ` Bhupinder Thakur
2017-06-19 11:01             ` Julien Grall
2017-06-19 11:47               ` Wei Liu
2017-06-19 13:11                 ` Bhupinder Thakur
2017-06-20 11:16                   ` Julien Grall
2017-06-20 11:42                     ` Wei Liu
2017-06-21 10:18                     ` Bhupinder Thakur
2017-06-06 17:25 ` [PATCH 07/14 v4] xen/arm: vpl011: Add a new vuart node in the xenstore Bhupinder Thakur
2017-06-06 23:38   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 08/14 v4] xen/arm: vpl011: Modify xenconsole to define and use a new console structure Bhupinder Thakur
2017-06-07  1:13   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 09/14 v4] xen/arm: vpl011: Modify xenconsole functions to take console structure as input Bhupinder Thakur
2017-06-07  0:43   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 10/14 v4] xen/arm: vpl011: Modify xenconsole to support multiple consoles Bhupinder Thakur
2017-06-07  1:03   ` Stefano Stabellini
2017-06-07  3:51     ` Bhupinder Thakur
2017-06-07 16:46       ` Wei Liu
2017-06-07 17:54       ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 11/14 v4] xen/arm: vpl011: Add support for vuart console in xenconsole Bhupinder Thakur
2017-06-07  1:08   ` Stefano Stabellini
2017-06-07 16:44   ` Wei Liu
2017-06-06 17:25 ` [PATCH 12/14 v4] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
2017-06-06 23:41   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 13/14 v4] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
2017-06-06 17:25 ` [PATCH 14/14 v4] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
2017-06-09 13:58 ` [PATCH 00/14 v4] PL011 emulation support in Xen Julien Grall
  -- strict thread matches above, loose matches on Subject: below --
2017-06-06 10:04 [PATCH 10/14 v4] xen/arm: vpl011: Modify xenconsole to support multiple consoles Bhupinder Thakur

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).