0c76f22ef1
- bnc#633573 - System fail to boot after running several warm reboot tests 22749-vtd-workarounds.patch - Upstream patches from Jan 22744-ept-pod-locking.patch 22777-vtd-ats-fixes.patch 22781-pod-hap-logdirty.patch 22782-x86-emul-smsw.patch 22789-i386-no-x2apic.patch 22790-svm-resume-migrate-pirqs.patch 22816-x86-pirq-drop-priv-check.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=94
453 lines
12 KiB
Diff
453 lines
12 KiB
Diff
Index: xen-4.0.2-testing/tools/misc/serial-split/Makefile
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ xen-4.0.2-testing/tools/misc/serial-split/Makefile
|
|
@@ -0,0 +1,20 @@
|
|
+CC ?= gcc
|
|
+CFLAGS ?= -Wall -Os
|
|
+CFILES = $(wildcard *.c)
|
|
+OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
|
|
+TARGET = serial-split
|
|
+
|
|
+all: $(TARGET)
|
|
+
|
|
+install: all
|
|
+ install -d $(DESTDIR)/usr/bin
|
|
+ install -s $(TARGET) $(DESTDIR)/usr/bin/
|
|
+
|
|
+clean:
|
|
+ rm *.o $(TARGET) *~
|
|
+
|
|
+$(TARGET): $(OBJS)
|
|
+ $(CC) $(CFLAGS) -o $@ $^
|
|
+
|
|
+%.o: %.c Makefile
|
|
+ $(CC) $(CFLAGS) -c -o $@ $<
|
|
Index: xen-4.0.2-testing/tools/misc/serial-split/serial-split.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ xen-4.0.2-testing/tools/misc/serial-split/serial-split.c
|
|
@@ -0,0 +1,422 @@
|
|
+/*
|
|
+ * serial-split.c
|
|
+ * pdb / console splitter
|
|
+ *
|
|
+ * Copyright 2005 Charles Coffing <ccoffing@novell.com>
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License
|
|
+ * as published by the Free Software Foundation; either version 2
|
|
+ * of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Typical setup:
|
|
+ *
|
|
+ * Development box Xen box
|
|
+ * ...-----+ +-----...
|
|
+ * +---------+ | |
|
|
+ * | gdb | | |
|
|
+ * | |\ high | |
|
|
+ * +---------+ \ | |
|
|
+ * \+-----------+ | serial | +------------------+
|
|
+ * | splitter |------------| Xen |
|
|
+ * /+-----------+ | | | - pdb (com1H)|
|
|
+ * +---------+ / | | | - printk (com1) |
|
|
+ * | console |/ low | | +------------------+
|
|
+ * | viewer | | |
|
|
+ * +---------+ | |
|
|
+ * ...-----+ +-----...
|
|
+ */
|
|
+
|
|
+
|
|
+#include <assert.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <fcntl.h>
|
|
+#include <termios.h>
|
|
+#include <sys/signal.h>
|
|
+#include <sys/time.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/wait.h>
|
|
+#include <sys/socket.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include <netinet/in.h>
|
|
+
|
|
+const unsigned int DefaultLowPort = 12010;
|
|
+const unsigned int DefaultBaud = 115200;
|
|
+const char DefaultSerialDevice[] = "/dev/ttyS0";
|
|
+
|
|
+#define DEBUG 0
|
|
+#define MAX(a,b) ((a)<(b)?(b):(a))
|
|
+
|
|
+
|
|
+static int cook_baud(int baud)
|
|
+{
|
|
+ int cooked_baud = 0;
|
|
+ switch (baud)
|
|
+ {
|
|
+ case 50: cooked_baud = B50; break;
|
|
+ case 75: cooked_baud = B75; break;
|
|
+ case 110: cooked_baud = B110; break;
|
|
+ case 134: cooked_baud = B134; break;
|
|
+ case 150: cooked_baud = B150; break;
|
|
+ case 200: cooked_baud = B200; break;
|
|
+ case 300: cooked_baud = B300; break;
|
|
+ case 600: cooked_baud = B600; break;
|
|
+ case 1200: cooked_baud = B1200; break;
|
|
+ case 1800: cooked_baud = B1800; break;
|
|
+ case 2400: cooked_baud = B2400; break;
|
|
+ case 4800: cooked_baud = B4800; break;
|
|
+ case 9600: cooked_baud = B9600; break;
|
|
+ case 19200: cooked_baud = B19200; break;
|
|
+ case 38400: cooked_baud = B38400; break;
|
|
+ case 57600: cooked_baud = B57600; break;
|
|
+ case 115200: cooked_baud = B115200; break;
|
|
+ }
|
|
+ return cooked_baud;
|
|
+}
|
|
+
|
|
+
|
|
+static int start_listener(unsigned short port)
|
|
+{
|
|
+ int fd;
|
|
+ struct sockaddr_in sin;
|
|
+ int on = 1;
|
|
+
|
|
+ if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
|
|
+ {
|
|
+ perror("socket");
|
|
+ goto out1;
|
|
+ }
|
|
+
|
|
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));
|
|
+
|
|
+ memset(&sin, 0, sizeof(sin));
|
|
+ sin.sin_family = AF_INET;
|
|
+ sin.sin_port = htons (port);
|
|
+ sin.sin_addr.s_addr = INADDR_ANY;
|
|
+ if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
|
|
+ {
|
|
+ perror("bind");
|
|
+ goto out2;
|
|
+ }
|
|
+
|
|
+ if (listen(fd, 1) < 0)
|
|
+ {
|
|
+ perror("listen");
|
|
+ goto out2;
|
|
+ }
|
|
+
|
|
+ fprintf(stderr, "Listening on port %d\n", port);
|
|
+
|
|
+ return fd;
|
|
+
|
|
+out2:
|
|
+ close(fd);
|
|
+out1:
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+
|
|
+static int accept_conn(int fd)
|
|
+{
|
|
+ int on = 1;
|
|
+ int new_fd;
|
|
+ struct sockaddr_in from;
|
|
+ socklen_t fromlen = sizeof(from);
|
|
+
|
|
+ new_fd = accept(fd, (struct sockaddr *)&from, &fromlen);
|
|
+ if (new_fd < 0)
|
|
+ perror("accept");
|
|
+ ioctl(new_fd, FIONBIO, &on);
|
|
+
|
|
+ fprintf(stderr, "Accepted connection on %d\n", new_fd);
|
|
+
|
|
+ return new_fd;
|
|
+}
|
|
+
|
|
+
|
|
+static void close_conn(int * fd)
|
|
+{
|
|
+ shutdown(*fd, 2);
|
|
+ close(*fd);
|
|
+ *fd = -1;
|
|
+}
|
|
+
|
|
+
|
|
+static int receive_data(int * fd, char * buf, ssize_t max_bytes, int * poll)
|
|
+{
|
|
+ ssize_t bytes;
|
|
+ if ((bytes = read(*fd, buf, max_bytes)) < 0)
|
|
+ {
|
|
+ perror("read");
|
|
+ *poll = 1;
|
|
+ return 0;
|
|
+ }
|
|
+ else if (bytes == 0)
|
|
+ {
|
|
+ close_conn(fd);
|
|
+ *poll = 0;
|
|
+ return 0;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (bytes == max_bytes)
|
|
+ *poll = 1;
|
|
+ else
|
|
+ *poll = 0;
|
|
+#if DEBUG
|
|
+ {
|
|
+ ssize_t i;
|
|
+ fprintf(stderr, "Received %d bytes on %d:\n", bytes, *fd);
|
|
+ for (i = 0; i < bytes; ++ i)
|
|
+ {
|
|
+ if ((i & 0xf) == 0)
|
|
+ printf(" ");
|
|
+ printf("%02x", buf[i] & 0xff);
|
|
+ if (((i+1) & 0xf) == 0 || i + 1 == bytes)
|
|
+ printf("\n");
|
|
+ else
|
|
+ printf(" ");
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+ return bytes;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void set_high_bit(char * buf, size_t bytes)
|
|
+{
|
|
+ size_t i;
|
|
+ for(i = 0; i < bytes; ++ i)
|
|
+ buf[i] |= 0x80;
|
|
+}
|
|
+
|
|
+
|
|
+static void clear_high_bit(char * buf, size_t bytes)
|
|
+{
|
|
+ size_t i;
|
|
+ for(i = 0; i < bytes; ++ i)
|
|
+ buf[i] &= 0x7f;
|
|
+}
|
|
+
|
|
+
|
|
+static int open_serial(char const * serial_dev, int baud)
|
|
+{
|
|
+ struct termios newsertio;
|
|
+ int serial_fd;
|
|
+ memset(&newsertio, 0, sizeof(newsertio));
|
|
+
|
|
+ if ((serial_fd = open(serial_dev, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0)
|
|
+ {
|
|
+ perror(serial_dev);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ newsertio.c_cflag = baud | CS8 | CLOCAL | CREAD;
|
|
+ newsertio.c_iflag = IGNBRK | IGNPAR; /* raw input */
|
|
+ newsertio.c_oflag = 0; /* raw output */
|
|
+ newsertio.c_lflag = 0; /* no echo, no signals */
|
|
+ newsertio.c_cc[VMIN] = 1;
|
|
+ newsertio.c_cc[VTIME] = 0;
|
|
+ tcflush(serial_fd, TCIFLUSH);
|
|
+ tcsetattr(serial_fd, TCSANOW, &newsertio);
|
|
+
|
|
+ fprintf(stderr, "Listening on %s\n", serial_dev);
|
|
+
|
|
+ return serial_fd;
|
|
+}
|
|
+
|
|
+
|
|
+static void main_loop(int serial_fd, int low_listener, int high_listener)
|
|
+{
|
|
+ fd_set rdfds;
|
|
+ int low_poll = 0, high_poll = 0, serial_poll = 0;
|
|
+ int low_fd = -1, high_fd = -1;
|
|
+
|
|
+ while(1)
|
|
+ {
|
|
+ char buf[1024];
|
|
+ ssize_t bytes;
|
|
+ int max;
|
|
+
|
|
+ FD_ZERO(&rdfds);
|
|
+ FD_SET(low_fd < 0 ? low_listener : low_fd, &rdfds);
|
|
+ FD_SET(high_fd < 0 ? high_listener : high_fd, &rdfds);
|
|
+ FD_SET(serial_fd, &rdfds);
|
|
+
|
|
+ max = MAX(low_fd, low_listener);
|
|
+ max = MAX(max, high_fd);
|
|
+ max = MAX(max, high_listener);
|
|
+ max = MAX(max, serial_fd);
|
|
+
|
|
+ if (select(max + 1, &rdfds, NULL, NULL, NULL) < 0)
|
|
+ {
|
|
+ perror("select");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (FD_ISSET(low_listener, &rdfds))
|
|
+ {
|
|
+ assert(low_fd < 0);
|
|
+ low_fd = accept_conn(low_listener);
|
|
+ }
|
|
+
|
|
+ if (FD_ISSET(high_listener, &rdfds))
|
|
+ {
|
|
+ assert(high_fd < 0);
|
|
+ high_fd = accept_conn(high_listener);
|
|
+ }
|
|
+
|
|
+ if (low_poll || (low_fd >= 0 && FD_ISSET(low_fd, &rdfds)))
|
|
+ {
|
|
+ if ((bytes = receive_data(&low_fd, &buf[0], sizeof(buf),
|
|
+ &low_poll)) > 0)
|
|
+ {
|
|
+ clear_high_bit(&buf[0], bytes);
|
|
+ if (write(serial_fd, &buf[0], bytes) < 0)
|
|
+ perror("write");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (high_poll || (high_fd >= 0 && FD_ISSET(high_fd, &rdfds)))
|
|
+ {
|
|
+ if ((bytes = receive_data(&high_fd, &buf[0], sizeof(buf),
|
|
+ &high_poll)) > 0)
|
|
+ {
|
|
+ set_high_bit(&buf[0], bytes);
|
|
+ if (write(serial_fd, &buf[0], bytes) < 0)
|
|
+ perror("write");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (serial_poll || FD_ISSET(serial_fd, &rdfds))
|
|
+ {
|
|
+ if ((bytes = receive_data(&serial_fd, &buf[0], sizeof(buf),
|
|
+ &serial_poll)) > 0)
|
|
+ {
|
|
+ ssize_t i;
|
|
+ for (i = 0; i < bytes; ++ i)
|
|
+ {
|
|
+ if (buf[i] & 0x80)
|
|
+ {
|
|
+ if (high_fd >= 0)
|
|
+ {
|
|
+ buf[i] &= 0x7f;
|
|
+ if ((write(high_fd, &buf[i], 1)) < 0)
|
|
+ {
|
|
+ perror("write");
|
|
+ close_conn(&high_fd);
|
|
+ high_poll = 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (low_fd >= 0)
|
|
+ {
|
|
+ if ((write(low_fd, &buf[i], 1)) < 0)
|
|
+ {
|
|
+ perror("write");
|
|
+ close_conn(&low_fd);
|
|
+ low_poll = 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void usage()
|
|
+{
|
|
+ printf(
|
|
+"Description:\n"
|
|
+" Splits the serial port between two TCP ports. Bytes read from the\n"
|
|
+" serial port will be delivered to one of the two TCP ports (high or\n"
|
|
+" low) depending on whether the high bit is set. Bytes written to the\n"
|
|
+" TCP ports will be forwarded to the serial port; the high bit will be\n"
|
|
+" set or cleared to denote the source.\n"
|
|
+"Usage:\n"
|
|
+" serial-split [-d<serial-device>] [-b<baud>]\n"
|
|
+" [-l<low-port>] [-h<high-port>]\n"
|
|
+"Parameters:\n"
|
|
+" -d<serial-device> Defaults to %s.\n"
|
|
+" -b<baud> Baud rate of the serial port. Defaults to %d.\n"
|
|
+" Also assumes 8N1.\n"
|
|
+" -l<low-port> Low TCP port. Defaults to %d, or one less than\n"
|
|
+" the high port.\n"
|
|
+" -h<high-port> High TCP port. Defaults to %d, or one more than\n"
|
|
+" the low port.\n",
|
|
+DefaultSerialDevice, DefaultBaud, DefaultLowPort, DefaultLowPort + 1);
|
|
+
|
|
+ exit(1);
|
|
+}
|
|
+
|
|
+
|
|
+int main(int argc, char **argv)
|
|
+{
|
|
+ int cooked_baud = cook_baud(DefaultBaud);
|
|
+ char const * serial_dev = DefaultSerialDevice;
|
|
+ int low_port = -1, high_port = -1;
|
|
+ int serial_fd, low_listener, high_listener;
|
|
+
|
|
+ while ( --argc != 0 )
|
|
+ {
|
|
+ char *p = argv[argc];
|
|
+ if ( *(p++) != '-' )
|
|
+ usage();
|
|
+ switch (*(p++))
|
|
+ {
|
|
+ case 'b':
|
|
+ if ( (cooked_baud = cook_baud(atoi(p))) == 0 )
|
|
+ {
|
|
+ fprintf(stderr, "Bad baud rate\n");
|
|
+ exit(1);
|
|
+ }
|
|
+ break;
|
|
+ case 'd':
|
|
+ serial_dev = p;
|
|
+ break;
|
|
+ case 'l':
|
|
+ if ((low_port = atoi(p)) <= 0)
|
|
+ usage();
|
|
+ break;
|
|
+ case 'h':
|
|
+ if ((high_port = atoi(p)) <= 0)
|
|
+ usage();
|
|
+ break;
|
|
+ default:
|
|
+ usage();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (low_port == -1 && high_port == -1)
|
|
+ low_port = DefaultLowPort;
|
|
+ if (low_port == -1)
|
|
+ low_port = high_port - 1;
|
|
+ if (high_port == -1)
|
|
+ high_port = low_port + 1;
|
|
+
|
|
+ if ((serial_fd = open_serial(serial_dev, cooked_baud)) < 0 ||
|
|
+ (low_listener = start_listener(low_port)) < 0 ||
|
|
+ (high_listener = start_listener(high_port)) < 0)
|
|
+ exit(1);
|
|
+
|
|
+ main_loop(serial_fd, low_listener, high_listener);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|