]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'remotes/ehabkost/tags/numa-pull-request' into staging
authorPeter Maydell <peter.maydell@linaro.org>
Fri, 3 Mar 2017 14:59:45 +0000 (14:59 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Fri, 3 Mar 2017 14:59:45 +0000 (14:59 +0000)
NUMA documentation update

# gpg: Signature made Fri 03 Mar 2017 13:11:25 GMT
# gpg:                using RSA key 0x2807936F984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/numa-pull-request:
  qemu-options: Rewrite -numa documentation

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
dtc
io/channel-websock.c
pc-bios/README
pc-bios/slof.bin
roms/SLOF

diff --git a/dtc b/dtc
index ec02b34c05be04f249ffaaca4b666f5246877dea..fa8bc7f928ac25f23532afc8beb2073efc8fb063 160000 (submodule)
--- a/dtc
+++ b/dtc
@@ -1 +1 @@
-Subproject commit ec02b34c05be04f249ffaaca4b666f5246877dea
+Subproject commit fa8bc7f928ac25f23532afc8beb2073efc8fb063
index e47279a1ae461771dfd2db82e96ae0ee601d6c45..8fabadea2f7f40bb5f2a20f5ed9d5b5af193f1b4 100644 (file)
 #define QIO_CHANNEL_WEBSOCK_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
 #define QIO_CHANNEL_WEBSOCK_GUID_LEN strlen(QIO_CHANNEL_WEBSOCK_GUID)
 
-#define QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL "Sec-WebSocket-Protocol"
-#define QIO_CHANNEL_WEBSOCK_HEADER_VERSION "Sec-WebSocket-Version"
-#define QIO_CHANNEL_WEBSOCK_HEADER_KEY "Sec-WebSocket-Key"
+#define QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL "sec-websocket-protocol"
+#define QIO_CHANNEL_WEBSOCK_HEADER_VERSION "sec-websocket-version"
+#define QIO_CHANNEL_WEBSOCK_HEADER_KEY "sec-websocket-key"
+#define QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE "upgrade"
+#define QIO_CHANNEL_WEBSOCK_HEADER_HOST "host"
+#define QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION "connection"
 
 #define QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY "binary"
+#define QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE "Upgrade"
+#define QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET "websocket"
 
 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RESPONSE  \
     "HTTP/1.1 101 Switching Protocols\r\n"      \
@@ -49,6 +54,9 @@
 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM "\r\n"
 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_END "\r\n\r\n"
 #define QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION "13"
+#define QIO_CHANNEL_WEBSOCK_HTTP_METHOD "GET"
+#define QIO_CHANNEL_WEBSOCK_HTTP_PATH "/"
+#define QIO_CHANNEL_WEBSOCK_HTTP_VERSION "HTTP/1.1"
 
 /* The websockets packet header is variable length
  * depending on the size of the payload... */
@@ -99,6 +107,13 @@ struct QEMU_PACKED QIOChannelWebsockHeader {
     } u;
 };
 
+typedef struct QIOChannelWebsockHTTPHeader QIOChannelWebsockHTTPHeader;
+
+struct QIOChannelWebsockHTTPHeader {
+    char *name;
+    char *value;
+};
+
 enum {
     QIO_CHANNEL_WEBSOCK_OPCODE_CONTINUATION = 0x0,
     QIO_CHANNEL_WEBSOCK_OPCODE_TEXT_FRAME = 0x1,
@@ -108,25 +123,130 @@ enum {
     QIO_CHANNEL_WEBSOCK_OPCODE_PONG = 0xA
 };
 
-static char *qio_channel_websock_handshake_entry(const char *handshake,
-                                                 size_t handshake_len,
-                                                 const char *name)
-{
-    char *begin, *end, *ret = NULL;
-    char *line = g_strdup_printf("%s%s: ",
-                                 QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM,
-                                 name);
-    begin = g_strstr_len(handshake, handshake_len, line);
-    if (begin != NULL) {
-        begin += strlen(line);
-        end = g_strstr_len(begin, handshake_len - (begin - handshake),
-                QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
-        if (end != NULL) {
-            ret = g_strndup(begin, end - begin);
+static size_t
+qio_channel_websock_extract_headers(char *buffer,
+                                    QIOChannelWebsockHTTPHeader *hdrs,
+                                    size_t nhdrsalloc,
+                                    Error **errp)
+{
+    char *nl, *sep, *tmp;
+    size_t nhdrs = 0;
+
+    /*
+     * First parse the HTTP protocol greeting of format:
+     *
+     *   $METHOD $PATH $VERSION
+     *
+     * e.g.
+     *
+     *   GET / HTTP/1.1
+     */
+
+    nl = strstr(buffer, QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
+    if (!nl) {
+        error_setg(errp, "Missing HTTP header delimiter");
+        return 0;
+    }
+    *nl = '\0';
+
+    tmp = strchr(buffer, ' ');
+    if (!tmp) {
+        error_setg(errp, "Missing HTTP path delimiter");
+        return 0;
+    }
+    *tmp = '\0';
+
+    if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_METHOD)) {
+        error_setg(errp, "Unsupported HTTP method %s", buffer);
+        return 0;
+    }
+
+    buffer = tmp + 1;
+    tmp = strchr(buffer, ' ');
+    if (!tmp) {
+        error_setg(errp, "Missing HTTP version delimiter");
+        return 0;
+    }
+    *tmp = '\0';
+
+    if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_PATH)) {
+        error_setg(errp, "Unexpected HTTP path %s", buffer);
+        return 0;
+    }
+
+    buffer = tmp + 1;
+
+    if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_VERSION)) {
+        error_setg(errp, "Unsupported HTTP version %s", buffer);
+        return 0;
+    }
+
+    buffer = nl + strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
+
+    /*
+     * Now parse all the header fields of format
+     *
+     *   $NAME: $VALUE
+     *
+     * e.g.
+     *
+     *   Cache-control: no-cache
+     */
+    do {
+        QIOChannelWebsockHTTPHeader *hdr;
+
+        nl = strstr(buffer, QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
+        if (nl) {
+            *nl = '\0';
+        }
+
+        sep = strchr(buffer, ':');
+        if (!sep) {
+            error_setg(errp, "Malformed HTTP header");
+            return 0;
+        }
+        *sep = '\0';
+        sep++;
+        while (*sep == ' ') {
+            sep++;
+        }
+
+        if (nhdrs >= nhdrsalloc) {
+            error_setg(errp, "Too many HTTP headers");
+            return 0;
+        }
+
+        hdr = &hdrs[nhdrs++];
+        hdr->name = buffer;
+        hdr->value = sep;
+
+        /* Canonicalize header name for easier identification later */
+        for (tmp = hdr->name; *tmp; tmp++) {
+            *tmp = g_ascii_tolower(*tmp);
+        }
+
+        if (nl) {
+            buffer = nl + strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
+        }
+    } while (nl != NULL);
+
+    return nhdrs;
+}
+
+static const char *
+qio_channel_websock_find_header(QIOChannelWebsockHTTPHeader *hdrs,
+                                size_t nhdrs,
+                                const char *name)
+{
+    size_t i;
+
+    for (i = 0; i < nhdrs; i++) {
+        if (g_str_equal(hdrs[i].name, name)) {
+            return hdrs[i].value;
         }
     }
-    g_free(line);
-    return ret;
+
+    return NULL;
 }
 
 
@@ -166,58 +286,90 @@ static int qio_channel_websock_handshake_send_response(QIOChannelWebsock *ioc,
 }
 
 static int qio_channel_websock_handshake_process(QIOChannelWebsock *ioc,
-                                                 const char *line,
-                                                 size_t size,
+                                                 char *buffer,
                                                  Error **errp)
 {
-    int ret = -1;
-    char *protocols = qio_channel_websock_handshake_entry(
-        line, size, QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL);
-    char *version = qio_channel_websock_handshake_entry(
-        line, size, QIO_CHANNEL_WEBSOCK_HEADER_VERSION);
-    char *key = qio_channel_websock_handshake_entry(
-        line, size, QIO_CHANNEL_WEBSOCK_HEADER_KEY);
+    QIOChannelWebsockHTTPHeader hdrs[32];
+    size_t nhdrs = G_N_ELEMENTS(hdrs);
+    const char *protocols = NULL, *version = NULL, *key = NULL,
+        *host = NULL, *connection = NULL, *upgrade = NULL;
 
+    nhdrs = qio_channel_websock_extract_headers(buffer, hdrs, nhdrs, errp);
+    if (!nhdrs) {
+        return -1;
+    }
+
+    protocols = qio_channel_websock_find_header(
+        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL);
     if (!protocols) {
         error_setg(errp, "Missing websocket protocol header data");
-        goto cleanup;
+        return -1;
     }
 
+    version = qio_channel_websock_find_header(
+        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_VERSION);
     if (!version) {
         error_setg(errp, "Missing websocket version header data");
-        goto cleanup;
+        return -1;
     }
 
+    key = qio_channel_websock_find_header(
+        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_KEY);
     if (!key) {
         error_setg(errp, "Missing websocket key header data");
-        goto cleanup;
+        return -1;
+    }
+
+    host = qio_channel_websock_find_header(
+        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_HOST);
+    if (!host) {
+        error_setg(errp, "Missing websocket host header data");
+        return -1;
+    }
+
+    connection = qio_channel_websock_find_header(
+        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION);
+    if (!connection) {
+        error_setg(errp, "Missing websocket connection header data");
+        return -1;
+    }
+
+    upgrade = qio_channel_websock_find_header(
+        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE);
+    if (!upgrade) {
+        error_setg(errp, "Missing websocket upgrade header data");
+        return -1;
     }
 
     if (!g_strrstr(protocols, QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY)) {
         error_setg(errp, "No '%s' protocol is supported by client '%s'",
                    QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY, protocols);
-        goto cleanup;
+        return -1;
     }
 
     if (!g_str_equal(version, QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION)) {
         error_setg(errp, "Version '%s' is not supported by client '%s'",
                    QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION, version);
-        goto cleanup;
+        return -1;
     }
 
     if (strlen(key) != QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN) {
         error_setg(errp, "Key length '%zu' was not as expected '%d'",
                    strlen(key), QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN);
-        goto cleanup;
+        return -1;
     }
 
-    ret = qio_channel_websock_handshake_send_response(ioc, key, errp);
+    if (!g_strrstr(connection, QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE)) {
+        error_setg(errp, "No connection upgrade requested '%s'", connection);
+        return -1;
+    }
 
- cleanup:
-    g_free(protocols);
-    g_free(version);
-    g_free(key);
-    return ret;
+    if (!g_str_equal(upgrade, QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET)) {
+        error_setg(errp, "Incorrect upgrade method '%s'", upgrade);
+        return -1;
+    }
+
+    return qio_channel_websock_handshake_send_response(ioc, key, errp);
 }
 
 static int qio_channel_websock_handshake_read(QIOChannelWebsock *ioc,
@@ -248,10 +400,10 @@ static int qio_channel_websock_handshake_read(QIOChannelWebsock *ioc,
             return 0;
         }
     }
+    *handshake_end = '\0';
 
     if (qio_channel_websock_handshake_process(ioc,
                                               (char *)ioc->encinput.buffer,
-                                              ioc->encinput.offset,
                                               errp) < 0) {
         return -1;
     }
@@ -570,21 +722,24 @@ static ssize_t qio_channel_websock_read_wire(QIOChannelWebsock *ioc,
         ioc->encinput.offset += ret;
     }
 
-    if (ioc->payload_remain == 0) {
-        ret = qio_channel_websock_decode_header(ioc, errp);
+    while (ioc->encinput.offset != 0) {
+        if (ioc->payload_remain == 0) {
+            ret = qio_channel_websock_decode_header(ioc, errp);
+            if (ret < 0) {
+                return ret;
+            }
+            if (ret == 0) {
+                ioc->io_eof = TRUE;
+                break;
+            }
+        }
+
+        ret = qio_channel_websock_decode_payload(ioc, errp);
         if (ret < 0) {
             return ret;
         }
-        if (ret == 0) {
-            return 0;
-        }
     }
-
-    ret = qio_channel_websock_decode_payload(ioc, errp);
-    if (ret < 0) {
-        return ret;
-    }
-    return ret;
+    return 1;
 }
 
 
@@ -642,9 +797,6 @@ static gboolean qio_channel_websock_flush(QIOChannel *ioc,
         if (ret < 0) {
             goto cleanup;
         }
-        if (ret == 0) {
-            wioc->io_eof = TRUE;
-        }
     }
 
  cleanup:
index 47a913f9c7cc41e70001e1bc86e5fc1e5ac5d5f1..dcead369bf5429b652706730e86e0ad0ffd041ec 100644 (file)
@@ -17,7 +17,7 @@
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
   https://github.com/aik/SLOF, and the image currently in qemu is
-  built from git tag qemu-slof-20161019.
+  built from git tag qemu-slof-20170303.
 
 - sgabios (the Serial Graphics Adapter option ROM) provides a means for
   legacy x86 software to communicate with an attached serial console as
index 30ce7ac384146c1a30c2b3067ccd532efe78f189..0408723dbf693e3385e4f023e5e2cfe5f715b5f5 100644 (file)
Binary files a/pc-bios/slof.bin and b/pc-bios/slof.bin differ
index efd65f49929d7db775b26066d538c8120ae3db94..66d250ef0fd06bb88b7399b9563b5008201f2d63 160000 (submodule)
--- a/roms/SLOF
+++ b/roms/SLOF
@@ -1 +1 @@
-Subproject commit efd65f49929d7db775b26066d538c8120ae3db94
+Subproject commit 66d250ef0fd06bb88b7399b9563b5008201f2d63