From: David Kershner <david.kershner@xxxxxxxxxx> Channel.h is used by all channels, it needs to be in include. Controlvm Channel is only used by visorbus, it needs to just be there. Signed-off-by: David Kershner <david.kershner@xxxxxxxxxx> Signed-off-by: Benjamin Romer <benjamin.romer@xxxxxxxxxx> --- .../unisys/common-spar/include/channels/channel.h | 590 --------------------- .../common-spar/include/channels/channel_guid.h | 61 --- .../include/channels/controlvmchannel.h | 485 ----------------- drivers/staging/unisys/include/channel.h | 555 +++++++++++++++++++ drivers/staging/unisys/include/channel_guid.h | 61 +++ drivers/staging/unisys/visorbus/controlvmchannel.h | 485 +++++++++++++++++ 6 files changed, 1101 insertions(+), 1136 deletions(-) delete mode 100644 drivers/staging/unisys/common-spar/include/channels/channel.h delete mode 100644 drivers/staging/unisys/common-spar/include/channels/channel_guid.h delete mode 100644 drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h create mode 100644 drivers/staging/unisys/include/channel.h create mode 100644 drivers/staging/unisys/include/channel_guid.h create mode 100644 drivers/staging/unisys/visorbus/controlvmchannel.h diff --git a/drivers/staging/unisys/common-spar/include/channels/channel.h b/drivers/staging/unisys/common-spar/include/channels/channel.h deleted file mode 100644 index 6fb6e5b..0000000 --- a/drivers/staging/unisys/common-spar/include/channels/channel.h +++ /dev/null @@ -1,590 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __CHANNEL_H__ -#define __CHANNEL_H__ - -#include <linux/types.h> -#include <linux/io.h> -#include <linux/uuid.h> - -/* -* Whenever this file is changed a corresponding change must be made in -* the Console/ServicePart/visordiag_early/supervisor_channel.h file -* which is needed for Linux kernel compiles. These two files must be -* in sync. -*/ - -/* define the following to prevent include nesting in kernel header - * files of similar abbreviated content - */ -#define __SUPERVISOR_CHANNEL_H__ - -#define SIGNATURE_16(A, B) ((A) | (B<<8)) -#define SIGNATURE_32(A, B, C, D) \ - (SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16)) -#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ - (SIGNATURE_32(A, B, C, D) | ((u64)(SIGNATURE_32(E, F, G, H)) << 32)) - -#ifndef lengthof -#define lengthof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER)) -#endif -#ifndef COVERQ -#define COVERQ(v, d) (((v)+(d)-1) / (d)) -#endif -#ifndef COVER -#define COVER(v, d) ((d)*COVERQ(v, d)) -#endif - -#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE SIGNATURE_32('E', 'C', 'N', 'L') - -enum channel_serverstate { - CHANNELSRV_UNINITIALIZED = 0, /* channel is in an undefined state */ - CHANNELSRV_READY = 1 /* channel has been initialized by server */ -}; - -enum channel_clientstate { - CHANNELCLI_DETACHED = 0, - CHANNELCLI_DISABLED = 1, /* client can see channel but is NOT - * allowed to use it unless given TBD - * explicit request (should actually be - * < DETACHED) */ - CHANNELCLI_ATTACHING = 2, /* legacy EFI client request - * for EFI server to attach */ - CHANNELCLI_ATTACHED = 3, /* idle, but client may want - * to use channel any time */ - CHANNELCLI_BUSY = 4, /* client either wants to use or is - * using channel */ - CHANNELCLI_OWNED = 5 /* "no worries" state - client can - * access channel anytime */ -}; - -static inline const u8 * -ULTRA_CHANNELCLI_STRING(u32 v) -{ - switch (v) { - case CHANNELCLI_DETACHED: - return (const u8 *)("DETACHED"); - case CHANNELCLI_DISABLED: - return (const u8 *)("DISABLED"); - case CHANNELCLI_ATTACHING: - return (const u8 *)("ATTACHING"); - case CHANNELCLI_ATTACHED: - return (const u8 *)("ATTACHED"); - case CHANNELCLI_BUSY: - return (const u8 *)("BUSY"); - case CHANNELCLI_OWNED: - return (const u8 *)("OWNED"); - default: - break; - } - return (const u8 *)("?"); -} - -#define SPAR_CHANNEL_SERVER_READY(ch) \ - (readl(&(ch)->srv_state) == CHANNELSRV_READY) - -#define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n) \ - (((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \ - ? (1) : (0)) - -#define SPAR_CHANNEL_CLIENT_CHK_TRANSITION(old, new, id, log, \ - file, line) \ - do { \ - if (!ULTRA_VALID_CHANNELCLI_TRANSITION(old, new)) \ - pr_info("%s Channel StateTransition INVALID! (%s) %s(%d)-->%s(%d) @%s:%d\n", \ - id, "CliState<x>", \ - ULTRA_CHANNELCLI_STRING(old), \ - old, \ - ULTRA_CHANNELCLI_STRING(new), \ - new, \ - pathname_last_n_nodes((u8 *)file, 4), \ - line); \ - } while (0) - -#define SPAR_CHANNEL_CLIENT_TRANSITION(ch, id, newstate, log) \ - do { \ - SPAR_CHANNEL_CLIENT_CHK_TRANSITION( \ - readl(&(((struct channel_header __iomem *)\ - (ch))->cli_state_os)), \ - newstate, id, log, __FILE__, __LINE__); \ - pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n", \ - id, "CliStateOS", \ - ULTRA_CHANNELCLI_STRING( \ - readl(&((struct channel_header __iomem *)\ - (ch))->cli_state_os)), \ - readl(&((struct channel_header __iomem *)\ - (ch))->cli_state_os), \ - ULTRA_CHANNELCLI_STRING(newstate), \ - newstate, \ - pathname_last_n_nodes(__FILE__, 4), __LINE__); \ - writel(newstate, &((struct channel_header __iomem *)\ - (ch))->cli_state_os); \ - mb(); /* required for channel synch */ \ - } while (0) - -/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */ -/* throttling invalid boot channel statetransition error due to client - * disabled */ -#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01 - -/* throttling invalid boot channel statetransition error due to client - * not attached */ -#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02 - -/* throttling invalid boot channel statetransition error due to busy channel */ -#define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04 - -/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */ -/* throttling invalid guest OS channel statetransition error due to - * client disabled */ -#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED 0x01 - -/* throttling invalid guest OS channel statetransition error due to - * client not attached */ -#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED 0x02 - -/* throttling invalid guest OS channel statetransition error due to - * busy channel */ -#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY 0x04 - -/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so -* that windows guest can look at the FeatureFlags in the io channel, -* and configure the windows driver to use interrupts or not based on -* this setting. This flag is set in uislib after the -* ULTRA_VHBA_init_channel is called. All feature bits for all -* channels should be defined here. The io channel feature bits are -* defined right here */ -#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1) -#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3) -#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4) -#define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5) -#define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6) - -#pragma pack(push, 1) /* both GCC and VC now allow this pragma */ -/* Common Channel Header */ -struct channel_header { - u64 signature; /* Signature */ - u32 legacy_state; /* DEPRECATED - being replaced by */ - /* / SrvState, CliStateBoot, and CliStateOS below */ - u32 header_size; /* sizeof(struct channel_header) */ - u64 size; /* Total size of this channel in bytes */ - u64 features; /* Flags to modify behavior */ - uuid_le chtype; /* Channel type: data, bus, control, etc. */ - u64 partition_handle; /* ID of guest partition */ - u64 handle; /* Device number of this channel in client */ - u64 ch_space_offset; /* Offset in bytes to channel specific area */ - u32 version_id; /* struct channel_header Version ID */ - u32 partition_index; /* Index of guest partition */ - uuid_le zone_uuid; /* Guid of Channel's zone */ - u32 cli_str_offset; /* offset from channel header to - * nul-terminated ClientString (0 if - * ClientString not present) */ - u32 cli_state_boot; /* CHANNEL_CLIENTSTATE of pre-boot - * EFI client of this channel */ - u32 cmd_state_cli; /* CHANNEL_COMMANDSTATE (overloaded in - * Windows drivers, see ServerStateUp, - * ServerStateDown, etc) */ - u32 cli_state_os; /* CHANNEL_CLIENTSTATE of Guest OS - * client of this channel */ - u32 ch_characteristic; /* CHANNEL_CHARACTERISTIC_<xxx> */ - u32 cmd_state_srv; /* CHANNEL_COMMANDSTATE (overloaded in - * Windows drivers, see ServerStateUp, - * ServerStateDown, etc) */ - u32 srv_state; /* CHANNEL_SERVERSTATE */ - u8 cli_error_boot; /* bits to indicate err states for - * boot clients, so err messages can - * be throttled */ - u8 cli_error_os; /* bits to indicate err states for OS - * clients, so err messages can be - * throttled */ - u8 filler[1]; /* Pad out to 128 byte cacheline */ - /* Please add all new single-byte values below here */ - u8 recover_channel; -}; - -#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0) - -/* Subheader for the Signal Type variation of the Common Channel */ -struct signal_queue_header { - /* 1st cache line */ - u32 version; /* SIGNAL_QUEUE_HEADER Version ID */ - u32 chtype; /* Queue type: storage, network */ - u64 size; /* Total size of this queue in bytes */ - u64 sig_base_offset; /* Offset to signal queue area */ - u64 features; /* Flags to modify behavior */ - u64 num_sent; /* Total # of signals placed in this queue */ - u64 num_overflows; /* Total # of inserts failed due to - * full queue */ - u32 signal_size; /* Total size of a signal for this queue */ - u32 max_slots; /* Max # of slots in queue, 1 slot is - * always empty */ - u32 max_signals; /* Max # of signals in queue - * (MaxSignalSlots-1) */ - u32 head; /* Queue head signal # */ - /* 2nd cache line */ - u64 num_received; /* Total # of signals removed from this queue */ - u32 tail; /* Queue tail signal # (on separate - * cache line) */ - u32 reserved1; /* Reserved field */ - u64 reserved2; /* Reserved field */ - u64 client_queue; - u64 num_irq_received; /* Total # of Interrupts received. This - * is incremented by the ISR in the - * guest windows driver */ - u64 num_empty; /* Number of times that visor_signal_remove - * is called and returned Empty - * Status. */ - u32 errorflags; /* Error bits set during SignalReinit - * to denote trouble with client's - * fields */ - u8 filler[12]; /* Pad out to 64 byte cacheline */ -}; - -#pragma pack(pop) - -#define spar_signal_init(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ) \ - do { \ - memset(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD)); \ - chan->QHDRFLD.version = ver; \ - chan->QHDRFLD.chtype = typ; \ - chan->QHDRFLD.size = sizeof(chan->QDATAFLD); \ - chan->QHDRFLD.signal_size = sizeof(QDATATYPE); \ - chan->QHDRFLD.sig_base_offset = (u64)(chan->QDATAFLD)- \ - (u64)(&chan->QHDRFLD); \ - chan->QHDRFLD.max_slots = \ - sizeof(chan->QDATAFLD)/sizeof(QDATATYPE); \ - chan->QHDRFLD.max_signals = chan->QHDRFLD.max_slots-1; \ - } while (0) - -/* Generic function useful for validating any type of channel when it is - * received by the client that will be accessing the channel. - * Note that <logCtx> is only needed for callers in the EFI environment, and - * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. - */ -static inline int -spar_check_channel_client(void __iomem *ch, - uuid_le expected_uuid, - char *chname, - u64 expected_min_bytes, - u32 expected_version, - u64 expected_signature) -{ - if (uuid_le_cmp(expected_uuid, NULL_UUID_LE) != 0) { - uuid_le guid; - - memcpy_fromio(&guid, - &((struct channel_header __iomem *)(ch))->chtype, - sizeof(guid)); - /* caller wants us to verify type GUID */ - if (uuid_le_cmp(guid, expected_uuid) != 0) { - pr_err("Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n", - chname, &expected_uuid, - &expected_uuid, &guid); - return 0; - } - } - if (expected_min_bytes > 0) { /* caller wants us to verify - * channel size */ - unsigned long long bytes = - readq(&((struct channel_header __iomem *) - (ch))->size); - if (bytes < expected_min_bytes) { - pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n", - chname, &expected_uuid, - (unsigned long long)expected_min_bytes, bytes); - return 0; - } - } - if (expected_version > 0) { /* caller wants us to verify - * channel version */ - unsigned long ver = readl(&((struct channel_header __iomem *) - (ch))->version_id); - if (ver != expected_version) { - pr_err("Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8lx\n", - chname, &expected_uuid, - (unsigned long)expected_version, ver); - return 0; - } - } - if (expected_signature > 0) { /* caller wants us to verify - * channel signature */ - unsigned long long sig = - readq(&((struct channel_header __iomem *) - (ch))->signature); - if (sig != expected_signature) { - pr_err("Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8llx actual=0x%-8.8llx\n", - chname, &expected_uuid, - expected_signature, sig); - return 0; - } - } - return 1; -} - -/* Generic function useful for validating any type of channel when it is about - * to be initialized by the server of the channel. - * Note that <logCtx> is only needed for callers in the EFI environment, and - * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. - */ -static inline int spar_check_channel_server(uuid_le typeuuid, char *name, - u64 expected_min_bytes, - u64 actual_bytes) -{ - if (expected_min_bytes > 0) /* caller wants us to verify - * channel size */ - if (actual_bytes < expected_min_bytes) { - pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8llx actual=0x%-8.8llx\n", - name, &typeuuid, expected_min_bytes, - actual_bytes); - return 0; - } - return 1; -} - -/* Given a file pathname <s> (with '/' or '\' separating directory nodes), - * returns a pointer to the beginning of a node within that pathname such - * that the number of nodes from that pointer to the end of the string is - * NOT more than <n>. Note that if the pathname has less than <n> nodes - * in it, the return pointer will be to the beginning of the string. - */ -static inline u8 * -pathname_last_n_nodes(u8 *s, unsigned int n) -{ - u8 *p = s; - unsigned int node_count = 0; - - while (*p != '\0') { - if ((*p == '/') || (*p == '\\')) - node_count++; - p++; - } - if (node_count <= n) - return s; - while (n > 0) { - p--; - if (p == s) - break; /* should never happen, unless someone - * is changing the string while we are - * looking at it!! */ - if ((*p == '/') || (*p == '\\')) - n--; - } - return p + 1; -} - -static inline int -spar_channel_client_acquire_os(void __iomem *ch, u8 *id) -{ - struct channel_header __iomem *hdr = ch; - - if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_DISABLED, - &hdr->cli_error_os); - /* throttle until acquire successful */ - - pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n", - id); - } - return 0; - } - if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) && - (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) { - /* Our competitor is DISABLED, so we can transition to OWNED */ - pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n", - id, "cli_state_os", - ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os), - ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED), - CHANNELCLI_OWNED); - writel(CHANNELCLI_OWNED, &hdr->cli_state_os); - mb(); /* required for channel synch */ - } - if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) { - if (readb(&hdr->cli_error_os) != 0) { - /* we are in an error msg throttling state; - * come out of it */ - pr_info("%s Channel OS client acquire now successful\n", - id); - writeb(0, &hdr->cli_error_os); - } - return 1; - } - - /* We have to do it the "hard way". We transition to BUSY, - * and can use the channel iff our competitor has not also - * transitioned to BUSY. */ - if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED, - &hdr->cli_error_os); - /* throttle until acquire successful */ - pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n", - id, ULTRA_CHANNELCLI_STRING( - readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os)); - } - return 0; - } - writel(CHANNELCLI_BUSY, &hdr->cli_state_os); - mb(); /* required for channel synch */ - if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_BUSY, - &hdr->cli_error_os); - /* throttle until acquire successful */ - pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n", - id); - } - /* reset busy */ - writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); - mb(); /* required for channel synch */ - return 0; - } - if (readb(&hdr->cli_error_os) != 0) { - /* we are in an error msg throttling state; come out of it */ - pr_info("%s Channel OS client acquire now successful\n", id); - writeb(0, &hdr->cli_error_os); - } - return 1; -} - -static inline void -spar_channel_client_release_os(void __iomem *ch, u8 *id) -{ - struct channel_header __iomem *hdr = ch; - - if (readb(&hdr->cli_error_os) != 0) { - /* we are in an error msg throttling state; come out of it */ - pr_info("%s Channel OS client error state cleared\n", id); - writeb(0, &hdr->cli_error_os); - } - if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) - return; - if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) { - pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n", - id, ULTRA_CHANNELCLI_STRING( - readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os)); - /* return; */ - } - writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* release busy */ -} - -/* -* Routine Description: -* Tries to insert the prebuilt signal pointed to by pSignal into the nth -* Queue of the Channel pointed to by pChannel -* -* Parameters: -* pChannel: (IN) points to the IO Channel -* Queue: (IN) nth Queue of the IO Channel -* pSignal: (IN) pointer to the signal -* -* Assumptions: -* - pChannel, Queue and pSignal are valid. -* - If insertion fails due to a full queue, the caller will determine the -* retry policy (e.g. wait & try again, report an error, etc.). -* -* Return value: 1 if the insertion succeeds, 0 if the queue was -* full. -*/ - -unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, - void *sig); - -/* -* Routine Description: -* Removes one signal from Channel pChannel's nth Queue at the -* time of the call and copies it into the memory pointed to by -* pSignal. -* -* Parameters: -* pChannel: (IN) points to the IO Channel -* Queue: (IN) nth Queue of the IO Channel -* pSignal: (IN) pointer to where the signals are to be copied -* -* Assumptions: -* - pChannel and Queue are valid. -* - pSignal points to a memory area large enough to hold queue's SignalSize -* -* Return value: 1 if the removal succeeds, 0 if the queue was -* empty. -*/ - -unsigned char spar_signal_remove(struct channel_header __iomem *ch, u32 queue, - void *sig); - -/* -* Routine Description: -* Removes all signals present in Channel pChannel's nth Queue at the -* time of the call and copies them into the memory pointed to by -* pSignal. Returns the # of signals copied as the value of the routine. -* -* Parameters: -* pChannel: (IN) points to the IO Channel -* Queue: (IN) nth Queue of the IO Channel -* pSignal: (IN) pointer to where the signals are to be copied -* -* Assumptions: -* - pChannel and Queue are valid. -* - pSignal points to a memory area large enough to hold Queue's MaxSignals -* # of signals, each of which is Queue's SignalSize. -* -* Return value: -* # of signals copied. -*/ -unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, - void *sig); - -/* -* Routine Description: -* Determine whether a signal queue is empty. -* -* Parameters: -* pChannel: (IN) points to the IO Channel -* Queue: (IN) nth Queue of the IO Channel -* -* Return value: -* 1 if the signal queue is empty, 0 otherwise. -*/ -unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, - u32 queue); - -#endif diff --git a/drivers/staging/unisys/common-spar/include/channels/channel_guid.h b/drivers/staging/unisys/common-spar/include/channels/channel_guid.h deleted file mode 100644 index 706363fc..0000000 --- a/drivers/staging/unisys/common-spar/include/channels/channel_guid.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * CHANNEL Guids - */ - -/* Used in IOChannel - * {414815ed-c58c-11da-95a9-00e08161165f} - */ -#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x414815ed, 0xc58c, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le spar_vhba_channel_protocol_uuid = - SPAR_VHBA_CHANNEL_PROTOCOL_UUID; - -/* Used in IOChannel - * {8cd5994d-c58e-11da-95a9-00e08161165f} - */ -#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le spar_vnic_channel_protocol_uuid = - SPAR_VNIC_CHANNEL_PROTOCOL_UUID; - -/* Used in IOChannel - * {72120008-4AAB-11DC-8530-444553544200} - */ -#define SPAR_SIOVM_UUID \ - UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ - 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) -static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; - -/* Used in visornoop/visornoop_main.c - * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} - */ -#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ - 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) - -static const uuid_le spar_controldirector_channel_protocol_uuid = - SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; - -/* Used in visorchipset/visorchipset_main.c - * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C} - */ -#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ - 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) diff --git a/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h b/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h deleted file mode 100644 index a50d9cf..0000000 --- a/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h +++ /dev/null @@ -1,485 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __CONTROLVMCHANNEL_H__ -#define __CONTROLVMCHANNEL_H__ - -#include <linux/uuid.h> -#include "channel.h" - -/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */ -#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \ - 0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d) - -#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE \ - ULTRA_CHANNEL_PROTOCOL_SIGNATURE -#define CONTROLVM_MESSAGE_MAX 64 - -/* Must increment this whenever you insert or delete fields within - * this channel struct. Also increment whenever you change the meaning - * of fields within this channel struct so as to break pre-existing - * software. Note that you can usually add fields to the END of the - * channel struct withOUT needing to increment this. - */ -#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID 1 - -#define SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch) \ - spar_check_channel_client(ch, \ - SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \ - "controlvm", \ - sizeof(struct spar_controlvm_channel_protocol), \ - ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \ - ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE) - -#define MAX_SERIAL_NUM 32 - -/* Defines for various channel queues */ -#define CONTROLVM_QUEUE_REQUEST 0 -#define CONTROLVM_QUEUE_RESPONSE 1 -#define CONTROLVM_QUEUE_EVENT 2 -#define CONTROLVM_QUEUE_ACK 3 - -/* Max num of messages stored during IOVM creation to be reused after crash */ -#define CONTROLVM_CRASHMSG_MAX 2 - -struct spar_segment_state { - u16 enabled:1; /* Bit 0: May enter other states */ - u16 active:1; /* Bit 1: Assigned to active partition */ - u16 alive:1; /* Bit 2: Configure message sent to - * service/server */ - u16 revoked:1; /* Bit 3: similar to partition state - * ShuttingDown */ - u16 allocated:1; /* Bit 4: memory (device/port number) - * has been selected by Command */ - u16 known:1; /* Bit 5: has been introduced to the - * service/guest partition */ - u16 ready:1; /* Bit 6: service/Guest partition has - * responded to introduction */ - u16 operating:1; /* Bit 7: resource is configured and - * operating */ - /* Note: don't use high bit unless we need to switch to ushort - * which is non-compliant */ -}; - -static const struct spar_segment_state segment_state_running = { - 1, 1, 1, 0, 1, 1, 1, 1 -}; - -static const struct spar_segment_state segment_state_paused = { - 1, 1, 1, 0, 1, 1, 1, 0 -}; - -static const struct spar_segment_state segment_state_standby = { - 1, 1, 0, 0, 1, 1, 1, 0 -}; - -/* Ids for commands that may appear in either queue of a ControlVm channel. - * - * Commands that are initiated by the command partition (CP), by an IO or - * console service partition (SP), or by a guest partition (GP)are: - * - issued on the RequestQueue queue (q #0) in the ControlVm channel - * - responded to on the ResponseQueue queue (q #1) in the ControlVm channel - * - * Events that are initiated by an IO or console service partition (SP) or - * by a guest partition (GP) are: - * - issued on the EventQueue queue (q #2) in the ControlVm channel - * - responded to on the EventAckQueue queue (q #3) in the ControlVm channel - */ -enum controlvm_id { - CONTROLVM_INVALID = 0, - /* SWITCH commands required Parameter: SwitchNumber */ - /* BUS commands required Parameter: BusNumber */ - CONTROLVM_BUS_CREATE = 0x101, /* CP --> SP, GP */ - CONTROLVM_BUS_DESTROY = 0x102, /* CP --> SP, GP */ - CONTROLVM_BUS_CONFIGURE = 0x104, /* CP --> SP */ - CONTROLVM_BUS_CHANGESTATE = 0x105, /* CP --> SP, GP */ - CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106, /* SP, GP --> CP */ -/* DEVICE commands required Parameter: BusNumber, DeviceNumber */ - - CONTROLVM_DEVICE_CREATE = 0x201, /* CP --> SP, GP */ - CONTROLVM_DEVICE_DESTROY = 0x202, /* CP --> SP, GP */ - CONTROLVM_DEVICE_CONFIGURE = 0x203, /* CP --> SP */ - CONTROLVM_DEVICE_CHANGESTATE = 0x204, /* CP --> SP, GP */ - CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205, /* SP, GP --> CP */ - CONTROLVM_DEVICE_RECONFIGURE = 0x206, /* CP --> Boot */ -/* CHIPSET commands */ - CONTROLVM_CHIPSET_INIT = 0x301, /* CP --> SP, GP */ - CONTROLVM_CHIPSET_STOP = 0x302, /* CP --> SP, GP */ - CONTROLVM_CHIPSET_READY = 0x304, /* CP --> SP */ - CONTROLVM_CHIPSET_SELFTEST = 0x305, /* CP --> SP */ - -}; - -struct irq_info { - u64 reserved1; - - /* specifies interrupt handle. It is used to retrieve the - * corresponding interrupt pin from Monitor; and the - * interrupt pin is used to connect to the corresponding - * interrupt. Used by IOPart-GP only. - */ - u64 recv_irq_handle; - - /* specifies interrupt vector. It, interrupt pin, and shared are - * used to connect to the corresponding interrupt. Used by - * IOPart-GP only. - */ - u32 recv_irq_vector; - - /* specifies if the recvInterrupt is shared. It, interrupt pin - * and vector are used to connect to 0 = not shared; 1 = shared. - * the corresponding interrupt. Used by IOPart-GP only. - */ - u8 recv_irq_shared; - u8 reserved[3]; /* Natural alignment purposes */ -}; - -struct pci_id { - u16 domain; - u8 bus; - u8 slot; - u8 func; - u8 reserved[3]; /* Natural alignment purposes */ -}; - -struct efi_spar_indication { - u64 boot_to_fw_ui:1; /* Bit 0: Stop in uefi ui */ - u64 clear_nvram:1; /* Bit 1: Clear NVRAM */ - u64 clear_cmos:1; /* Bit 2: Clear CMOS */ - u64 boot_to_tool:1; /* Bit 3: Run install tool */ - /* remaining bits are available */ -}; - -enum ultra_chipset_feature { - ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001, - ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002, -}; - -/* This is the common structure that is at the beginning of every - * ControlVm message (both commands and responses) in any ControlVm - * queue. Commands are easily distinguished from responses by - * looking at the flags.response field. - */ -struct controlvm_message_header { - u32 id; /* See CONTROLVM_ID. */ - /* For requests, indicates the message type. */ - /* For responses, indicates the type of message we are responding to. */ - - u32 message_size; /* Includes size of this struct + size - * of message */ - u32 segment_index; /* Index of segment containing Vm - * message/information */ - u32 completion_status; /* Error status code or result of - * message completion */ - struct { - u32 failed:1; /* =1 in a response to * signify - * failure */ - u32 response_expected:1; /* =1 in all messages that expect a - * response (Control ignores this - * bit) */ - u32 server:1; /* =1 in all bus & device-related - * messages where the message - * receiver is to act as the bus or - * device server */ - u32 test_message:1; /* =1 for testing use only - * (Control and Command ignore this - * bit) */ - u32 partial_completion:1; /* =1 if there are forthcoming - * responses/acks associated - * with this message */ - u32 preserve:1; /* =1 this is to let us know to - * preserve channel contents - * (for running guests)*/ - u32 writer_in_diag:1; /* =1 the DiagWriter is active in the - * Diagnostic Partition*/ - } flags; - u32 reserved; /* Natural alignment */ - u64 message_handle; /* Identifies the particular message instance, - * and is used to match particular */ - /* request instances with the corresponding response instance. */ - u64 payload_vm_offset; /* Offset of payload area from start of this - * instance of ControlVm segment */ - u32 payload_max_bytes; /* Maximum bytes allocated in payload - * area of ControlVm segment */ - u32 payload_bytes; /* Actual number of bytes of payload - * area to copy between IO/Command; */ - /* if non-zero, there is a payload to copy. */ -}; - -struct controlvm_packet_device_create { - u32 bus_no; /* bus # (0..n-1) from the msg receiver's end */ - u32 dev_no; /* bus-relative (0..n-1) device number */ - u64 channel_addr; /* Guest physical address of the channel, which - * can be dereferenced by the receiver of this - * ControlVm command */ - u64 channel_bytes; /* specifies size of the channel in bytes */ - uuid_le data_type_uuid; /* specifies format of data in channel */ - uuid_le dev_inst_uuid; /* instance guid for the device */ - struct irq_info intr; /* specifies interrupt information */ -}; /* for CONTROLVM_DEVICE_CREATE */ - -struct controlvm_packet_device_configure { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - /* Control uses header SegmentIndex field to access bus number... */ - u32 dev_no; /* bus-relative (0..n-1) device number */ -} ; /* for CONTROLVM_DEVICE_CONFIGURE */ - -struct controlvm_message_device_create { - struct controlvm_message_header header; - struct controlvm_packet_device_create packet; -}; /* total 128 bytes */ - -struct controlvm_message_device_configure { - struct controlvm_message_header header; - struct controlvm_packet_device_configure packet; -}; /* total 56 bytes */ - -/* This is the format for a message in any ControlVm queue. */ -struct controlvm_message_packet { - union { - struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 dev_count; /* indicates the max number of - * devices on this bus */ - u64 channel_addr; /* Guest physical address of - * the channel, which can be - * dereferenced by the receiver - * of this ControlVm command */ - u64 channel_bytes; /* size of the channel */ - uuid_le bus_data_type_uuid; /* indicates format of - * data in bus channel*/ - uuid_le bus_inst_uuid; /* instance uuid for the bus */ - } create_bus; /* for CONTROLVM_BUS_CREATE */ - struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 reserved; /* Natural alignment purposes */ - } destroy_bus; /* for CONTROLVM_BUS_DESTROY */ - struct { - u32 bus_no; /* bus # (0..n-1) from the receiver's - * perspective */ - u32 reserved1; /* for alignment purposes */ - u64 guest_handle; /* This is used to convert - * guest physical address to - * physical address */ - u64 recv_bus_irq_handle; - /* specifies interrupt info. It is used by SP - * to register to receive interrupts from the - * CP. This interrupt is used for bus level - * notifications. The corresponding - * sendBusInterruptHandle is kept in CP. */ - } configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ - /* for CONTROLVM_DEVICE_CREATE */ - struct controlvm_packet_device_create create_device; - struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 dev_no; /* bus-relative (0..n-1) device # */ - } destroy_device; /* for CONTROLVM_DEVICE_DESTROY */ - /* for CONTROLVM_DEVICE_CONFIGURE */ - struct controlvm_packet_device_configure configure_device; - struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 dev_no; /* bus-relative (0..n-1) device # */ - } reconfigure_device; /* for CONTROLVM_DEVICE_RECONFIGURE */ - struct { - u32 bus_no; - struct spar_segment_state state; - u8 reserved[2]; /* Natural alignment purposes */ - } bus_change_state; /* for CONTROLVM_BUS_CHANGESTATE */ - struct { - u32 bus_no; - u32 dev_no; - struct spar_segment_state state; - struct { - u32 phys_device:1; /* =1 if message is for - * a physical device */ - } flags; - u8 reserved[2]; /* Natural alignment purposes */ - } device_change_state; /* for CONTROLVM_DEVICE_CHANGESTATE */ - struct { - u32 bus_no; - u32 dev_no; - struct spar_segment_state state; - u8 reserved[6]; /* Natural alignment purposes */ - } device_change_state_event; - /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */ - struct { - u32 bus_count; /* indicates the max number of busses */ - u32 switch_count; /* indicates the max number of - * switches if a service partition */ - enum ultra_chipset_feature features; - u32 platform_number; /* Platform Number */ - } init_chipset; /* for CONTROLVM_CHIPSET_INIT */ - struct { - u32 options; /* reserved */ - u32 test; /* bit 0 set to run embedded selftest */ - } chipset_selftest; /* for CONTROLVM_CHIPSET_SELFTEST */ - u64 addr; /* a physical address of something, that can be - * dereferenced by the receiver of this - * ControlVm command (depends on command id) */ - u64 handle; /* a handle of something (depends on command - * id) */ - }; -}; - -/* All messages in any ControlVm queue have this layout. */ -struct controlvm_message { - struct controlvm_message_header hdr; - struct controlvm_message_packet cmd; -}; - -struct spar_controlvm_channel_protocol { - struct channel_header header; - u64 gp_controlvm; /* guest phys addr of this channel */ - u64 gp_partition_tables;/* guest phys addr of partition tables */ - u64 gp_diag_guest; /* guest phys addr of diagnostic channel */ - u64 gp_boot_romdisk;/* guest phys addr of (read* only) Boot ROM disk */ - u64 gp_boot_ramdisk;/* guest phys addr of writable Boot RAM disk */ - u64 gp_acpi_table; /* guest phys addr of acpi table */ - u64 gp_control_channel;/* guest phys addr of control channel */ - u64 gp_diag_romdisk;/* guest phys addr of diagnostic ROM disk */ - u64 gp_nvram; /* guest phys addr of NVRAM channel */ - u64 request_payload_offset; /* Offset to request payload area */ - u64 event_payload_offset; /* Offset to event payload area */ - u32 request_payload_bytes; /* Bytes available in request payload - * area */ - u32 event_payload_bytes;/* Bytes available in event payload area */ - u32 control_channel_bytes; - u32 nvram_channel_bytes; /* Bytes in PartitionNvram segment */ - u32 message_bytes; /* sizeof(CONTROLVM_MESSAGE) */ - u32 message_count; /* CONTROLVM_MESSAGE_MAX */ - u64 gp_smbios_table; /* guest phys addr of SMBIOS tables */ - u64 gp_physical_smbios_table; /* guest phys addr of SMBIOS table */ - /* ULTRA_MAX_GUESTS_PER_SERVICE */ - char gp_reserved[2688]; - - /* guest physical address of EFI firmware image base */ - u64 virtual_guest_firmware_image_base; - - /* guest physical address of EFI firmware entry point */ - u64 virtual_guest_firmware_entry_point; - - /* guest EFI firmware image size */ - u64 virtual_guest_firmware_image_size; - - /* GPA = 1MB where EFI firmware image is copied to */ - u64 virtual_guest_firmware_boot_base; - u64 virtual_guest_image_base; - u64 virtual_guest_image_size; - u64 prototype_control_channel_offset; - u64 virtual_guest_partition_handle; - - u16 restore_action; /* Restore Action field to restore the guest - * partition */ - u16 dump_action; /* For Windows guests it shows if the visordisk - * is running in dump mode */ - u16 nvram_fail_count; - u16 saved_crash_message_count; /* = CONTROLVM_CRASHMSG_MAX */ - u32 saved_crash_message_offset; /* Offset to request payload area needed - * for crash dump */ - u32 installation_error; /* Type of error encountered during - * installation */ - u32 installation_text_id; /* Id of string to display */ - u16 installation_remaining_steps;/* Number of remaining installation - * steps (for progress bars) */ - u8 tool_action; /* ULTRA_TOOL_ACTIONS Installation Action - * field */ - u8 reserved; /* alignment */ - struct efi_spar_indication efi_spar_ind; - struct efi_spar_indication efi_spar_ind_supported; - u32 sp_reserved; - u8 reserved2[28]; /* Force signals to begin on 128-byte cache - * line */ - struct signal_queue_header request_queue;/* Service or guest partition - * uses this queue to send - * requests to Control */ - struct signal_queue_header response_queue;/* Control uses this queue to - * respond to service or guest - * partition requests */ - struct signal_queue_header event_queue; /* Control uses this queue to - * send events to service or - * guest partition */ - struct signal_queue_header event_ack_queue;/* Service or guest partition - * uses this queue to ack - * Control events */ - - /* Request fixed-size message pool - does not include payload */ - struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX]; - - /* Response fixed-size message pool - does not include payload */ - struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX]; - - /* Event fixed-size message pool - does not include payload */ - struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX]; - - /* Ack fixed-size message pool - does not include payload */ - struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX]; - - /* Message stored during IOVM creation to be reused after crash */ - struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX]; -}; - -/* Offsets for VM channel attributes */ -#define VM_CH_REQ_QUEUE_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, request_queue) -#define VM_CH_RESP_QUEUE_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, response_queue) -#define VM_CH_EVENT_QUEUE_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, event_queue) -#define VM_CH_ACK_QUEUE_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, event_ack_queue) -#define VM_CH_REQ_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, request_msg) -#define VM_CH_RESP_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, response_msg) -#define VM_CH_EVENT_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, event_msg) -#define VM_CH_ACK_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, event_ack_msg) -#define VM_CH_CRASH_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, saved_crash_msg) - -/* The following header will be located at the beginning of PayloadVmOffset for - * various ControlVm commands. The receiver of a ControlVm command with a - * PayloadVmOffset will dereference this address and then use connection_offset, - * initiator_offset, and target_offset to get the location of UTF-8 formatted - * strings that can be parsed to obtain command-specific information. The value - * of total_length should equal PayloadBytes. The format of the strings at - * PayloadVmOffset will take different forms depending on the message. - */ -struct spar_controlvm_parameters_header { - u32 total_length; - u32 header_length; - u32 connection_offset; - u32 connection_length; - u32 initiator_offset; - u32 initiator_length; - u32 target_offset; - u32 target_length; - u32 client_offset; - u32 client_length; - u32 name_offset; - u32 name_length; - uuid_le id; - u32 revision; - u32 reserved; /* Natural alignment */ -}; - -#endif /* __CONTROLVMCHANNEL_H__ */ diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h new file mode 100644 index 0000000..da0b538 --- /dev/null +++ b/drivers/staging/unisys/include/channel.h @@ -0,0 +1,555 @@ +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __CHANNEL_H__ +#define __CHANNEL_H__ + +#include <linux/types.h> +#include <linux/io.h> +#include <linux/uuid.h> + +/* +* Whenever this file is changed a corresponding change must be made in +* the Console/ServicePart/visordiag_early/supervisor_channel.h file +* which is needed for Linux kernel compiles. These two files must be +* in sync. +*/ + +/* define the following to prevent include nesting in kernel header + * files of similar abbreviated content + */ +#define __SUPERVISOR_CHANNEL_H__ + +#define SIGNATURE_16(A, B) ((A) | (B<<8)) +#define SIGNATURE_32(A, B, C, D) \ + (SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16)) +#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (SIGNATURE_32(A, B, C, D) | ((u64)(SIGNATURE_32(E, F, G, H)) << 32)) + +#ifndef lengthof +#define lengthof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER)) +#endif +#ifndef COVERQ +#define COVERQ(v, d) (((v)+(d)-1) / (d)) +#endif +#ifndef COVER +#define COVER(v, d) ((d)*COVERQ(v, d)) +#endif + +#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE SIGNATURE_32('E', 'C', 'N', 'L') + +enum channel_serverstate { + CHANNELSRV_UNINITIALIZED = 0, /* channel is in an undefined state */ + CHANNELSRV_READY = 1 /* channel has been initialized by server */ +}; + +enum channel_clientstate { + CHANNELCLI_DETACHED = 0, + CHANNELCLI_DISABLED = 1, /* client can see channel but is NOT + * allowed to use it unless given TBD + * explicit request (should actually be + * < DETACHED) */ + CHANNELCLI_ATTACHING = 2, /* legacy EFI client request + * for EFI server to attach */ + CHANNELCLI_ATTACHED = 3, /* idle, but client may want + * to use channel any time */ + CHANNELCLI_BUSY = 4, /* client either wants to use or is + * using channel */ + CHANNELCLI_OWNED = 5 /* "no worries" state - client can + * access channel anytime */ +}; + +static inline const u8 * +ULTRA_CHANNELCLI_STRING(u32 v) +{ + switch (v) { + case CHANNELCLI_DETACHED: + return (const u8 *)("DETACHED"); + case CHANNELCLI_DISABLED: + return (const u8 *)("DISABLED"); + case CHANNELCLI_ATTACHING: + return (const u8 *)("ATTACHING"); + case CHANNELCLI_ATTACHED: + return (const u8 *)("ATTACHED"); + case CHANNELCLI_BUSY: + return (const u8 *)("BUSY"); + case CHANNELCLI_OWNED: + return (const u8 *)("OWNED"); + default: + break; + } + return (const u8 *)("?"); +} + +#define SPAR_CHANNEL_SERVER_READY(ch) \ + (readl(&(ch)->srv_state) == CHANNELSRV_READY) + +#define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n) \ + (((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \ + (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \ + (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \ + (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \ + (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \ + (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \ + (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \ + (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \ + (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) || \ + (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) || \ + (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \ + (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \ + (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \ + (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \ + (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \ + ? (1) : (0)) + +/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */ +/* throttling invalid boot channel statetransition error due to client + * disabled */ +#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01 + +/* throttling invalid boot channel statetransition error due to client + * not attached */ +#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02 + +/* throttling invalid boot channel statetransition error due to busy channel */ +#define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04 + +/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */ +/* throttling invalid guest OS channel statetransition error due to + * client disabled */ +#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED 0x01 + +/* throttling invalid guest OS channel statetransition error due to + * client not attached */ +#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED 0x02 + +/* throttling invalid guest OS channel statetransition error due to + * busy channel */ +#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY 0x04 + +/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so +* that windows guest can look at the FeatureFlags in the io channel, +* and configure the windows driver to use interrupts or not based on +* this setting. This flag is set in uislib after the +* ULTRA_VHBA_init_channel is called. All feature bits for all +* channels should be defined here. The io channel feature bits are +* defined right here */ +#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1) +#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3) +#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4) +#define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5) +#define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6) + +#pragma pack(push, 1) /* both GCC and VC now allow this pragma */ +/* Common Channel Header */ +struct channel_header { + u64 signature; /* Signature */ + u32 legacy_state; /* DEPRECATED - being replaced by */ + /* / SrvState, CliStateBoot, and CliStateOS below */ + u32 header_size; /* sizeof(struct channel_header) */ + u64 size; /* Total size of this channel in bytes */ + u64 features; /* Flags to modify behavior */ + uuid_le chtype; /* Channel type: data, bus, control, etc. */ + u64 partition_handle; /* ID of guest partition */ + u64 handle; /* Device number of this channel in client */ + u64 ch_space_offset; /* Offset in bytes to channel specific area */ + u32 version_id; /* struct channel_header Version ID */ + u32 partition_index; /* Index of guest partition */ + uuid_le zone_uuid; /* Guid of Channel's zone */ + u32 cli_str_offset; /* offset from channel header to + * nul-terminated ClientString (0 if + * ClientString not present) */ + u32 cli_state_boot; /* CHANNEL_CLIENTSTATE of pre-boot + * EFI client of this channel */ + u32 cmd_state_cli; /* CHANNEL_COMMANDSTATE (overloaded in + * Windows drivers, see ServerStateUp, + * ServerStateDown, etc) */ + u32 cli_state_os; /* CHANNEL_CLIENTSTATE of Guest OS + * client of this channel */ + u32 ch_characteristic; /* CHANNEL_CHARACTERISTIC_<xxx> */ + u32 cmd_state_srv; /* CHANNEL_COMMANDSTATE (overloaded in + * Windows drivers, see ServerStateUp, + * ServerStateDown, etc) */ + u32 srv_state; /* CHANNEL_SERVERSTATE */ + u8 cli_error_boot; /* bits to indicate err states for + * boot clients, so err messages can + * be throttled */ + u8 cli_error_os; /* bits to indicate err states for OS + * clients, so err messages can be + * throttled */ + u8 filler[1]; /* Pad out to 128 byte cacheline */ + /* Please add all new single-byte values below here */ + u8 recover_channel; +}; + +#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0) + +/* Subheader for the Signal Type variation of the Common Channel */ +struct signal_queue_header { + /* 1st cache line */ + u32 version; /* SIGNAL_QUEUE_HEADER Version ID */ + u32 chtype; /* Queue type: storage, network */ + u64 size; /* Total size of this queue in bytes */ + u64 sig_base_offset; /* Offset to signal queue area */ + u64 features; /* Flags to modify behavior */ + u64 num_sent; /* Total # of signals placed in this queue */ + u64 num_overflows; /* Total # of inserts failed due to + * full queue */ + u32 signal_size; /* Total size of a signal for this queue */ + u32 max_slots; /* Max # of slots in queue, 1 slot is + * always empty */ + u32 max_signals; /* Max # of signals in queue + * (MaxSignalSlots-1) */ + u32 head; /* Queue head signal # */ + /* 2nd cache line */ + u64 num_received; /* Total # of signals removed from this queue */ + u32 tail; /* Queue tail signal # (on separate + * cache line) */ + u32 reserved1; /* Reserved field */ + u64 reserved2; /* Reserved field */ + u64 client_queue; + u64 num_irq_received; /* Total # of Interrupts received. This + * is incremented by the ISR in the + * guest windows driver */ + u64 num_empty; /* Number of times that visor_signal_remove + * is called and returned Empty + * Status. */ + u32 errorflags; /* Error bits set during SignalReinit + * to denote trouble with client's + * fields */ + u8 filler[12]; /* Pad out to 64 byte cacheline */ +}; + +#pragma pack(pop) + +#define spar_signal_init(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ) \ + do { \ + memset(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD)); \ + chan->QHDRFLD.version = ver; \ + chan->QHDRFLD.chtype = typ; \ + chan->QHDRFLD.size = sizeof(chan->QDATAFLD); \ + chan->QHDRFLD.signal_size = sizeof(QDATATYPE); \ + chan->QHDRFLD.sig_base_offset = (u64)(chan->QDATAFLD)- \ + (u64)(&chan->QHDRFLD); \ + chan->QHDRFLD.max_slots = \ + sizeof(chan->QDATAFLD)/sizeof(QDATATYPE); \ + chan->QHDRFLD.max_signals = chan->QHDRFLD.max_slots-1; \ + } while (0) + +/* Generic function useful for validating any type of channel when it is + * received by the client that will be accessing the channel. + * Note that <logCtx> is only needed for callers in the EFI environment, and + * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. + */ +static inline int +spar_check_channel_client(void __iomem *ch, + uuid_le expected_uuid, + char *chname, + u64 expected_min_bytes, + u32 expected_version, + u64 expected_signature) +{ + if (uuid_le_cmp(expected_uuid, NULL_UUID_LE) != 0) { + uuid_le guid; + + memcpy_fromio(&guid, + &((struct channel_header __iomem *)(ch))->chtype, + sizeof(guid)); + /* caller wants us to verify type GUID */ + if (uuid_le_cmp(guid, expected_uuid) != 0) { + pr_err("Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n", + chname, &expected_uuid, + &expected_uuid, &guid); + return 0; + } + } + if (expected_min_bytes > 0) { /* caller wants us to verify + * channel size */ + unsigned long long bytes = + readq(&((struct channel_header __iomem *) + (ch))->size); + if (bytes < expected_min_bytes) { + pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n", + chname, &expected_uuid, + (unsigned long long)expected_min_bytes, bytes); + return 0; + } + } + if (expected_version > 0) { /* caller wants us to verify + * channel version */ + unsigned long ver = readl(&((struct channel_header __iomem *) + (ch))->version_id); + if (ver != expected_version) { + pr_err("Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8lx\n", + chname, &expected_uuid, + (unsigned long)expected_version, ver); + return 0; + } + } + if (expected_signature > 0) { /* caller wants us to verify + * channel signature */ + unsigned long long sig = + readq(&((struct channel_header __iomem *) + (ch))->signature); + if (sig != expected_signature) { + pr_err("Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8llx actual=0x%-8.8llx\n", + chname, &expected_uuid, + expected_signature, sig); + return 0; + } + } + return 1; +} + +/* Generic function useful for validating any type of channel when it is about + * to be initialized by the server of the channel. + * Note that <logCtx> is only needed for callers in the EFI environment, and + * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. + */ +static inline int spar_check_channel_server(uuid_le typeuuid, char *name, + u64 expected_min_bytes, + u64 actual_bytes) +{ + if (expected_min_bytes > 0) /* caller wants us to verify + * channel size */ + if (actual_bytes < expected_min_bytes) { + pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8llx actual=0x%-8.8llx\n", + name, &typeuuid, expected_min_bytes, + actual_bytes); + return 0; + } + return 1; +} + +/* Given a file pathname <s> (with '/' or '\' separating directory nodes), + * returns a pointer to the beginning of a node within that pathname such + * that the number of nodes from that pointer to the end of the string is + * NOT more than <n>. Note that if the pathname has less than <n> nodes + * in it, the return pointer will be to the beginning of the string. + */ +static inline u8 * +pathname_last_n_nodes(u8 *s, unsigned int n) +{ + u8 *p = s; + unsigned int node_count = 0; + + while (*p != '\0') { + if ((*p == '/') || (*p == '\\')) + node_count++; + p++; + } + if (node_count <= n) + return s; + while (n > 0) { + p--; + if (p == s) + break; /* should never happen, unless someone + * is changing the string while we are + * looking at it!! */ + if ((*p == '/') || (*p == '\\')) + n--; + } + return p + 1; +} + +static inline int +spar_channel_client_acquire_os(void __iomem *ch, u8 *id) +{ + struct channel_header __iomem *hdr = ch; + + if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) { + if ((readb(&hdr->cli_error_os) + & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) { + /* we are NOT throttling this message */ + writeb(readb(&hdr->cli_error_os) | + ULTRA_CLIERROROS_THROTTLEMSG_DISABLED, + &hdr->cli_error_os); + /* throttle until acquire successful */ + + pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n", + id); + } + return 0; + } + if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) && + (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) { + /* Our competitor is DISABLED, so we can transition to OWNED */ + pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n", + id, "cli_state_os", + ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)), + readl(&hdr->cli_state_os), + ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED), + CHANNELCLI_OWNED); + writel(CHANNELCLI_OWNED, &hdr->cli_state_os); + mb(); /* required for channel synch */ + } + if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) { + if (readb(&hdr->cli_error_os) != 0) { + /* we are in an error msg throttling state; + * come out of it */ + pr_info("%s Channel OS client acquire now successful\n", + id); + writeb(0, &hdr->cli_error_os); + } + return 1; + } + + /* We have to do it the "hard way". We transition to BUSY, + * and can use the channel iff our competitor has not also + * transitioned to BUSY. */ + if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) { + if ((readb(&hdr->cli_error_os) + & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) { + /* we are NOT throttling this message */ + writeb(readb(&hdr->cli_error_os) | + ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED, + &hdr->cli_error_os); + /* throttle until acquire successful */ + pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n", + id, ULTRA_CHANNELCLI_STRING( + readl(&hdr->cli_state_os)), + readl(&hdr->cli_state_os)); + } + return 0; + } + writel(CHANNELCLI_BUSY, &hdr->cli_state_os); + mb(); /* required for channel synch */ + if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) { + if ((readb(&hdr->cli_error_os) + & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) { + /* we are NOT throttling this message */ + writeb(readb(&hdr->cli_error_os) | + ULTRA_CLIERROROS_THROTTLEMSG_BUSY, + &hdr->cli_error_os); + /* throttle until acquire successful */ + pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n", + id); + } + /* reset busy */ + writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); + mb(); /* required for channel synch */ + return 0; + } + if (readb(&hdr->cli_error_os) != 0) { + /* we are in an error msg throttling state; come out of it */ + pr_info("%s Channel OS client acquire now successful\n", id); + writeb(0, &hdr->cli_error_os); + } + return 1; +} + +static inline void +spar_channel_client_release_os(void __iomem *ch, u8 *id) +{ + struct channel_header __iomem *hdr = ch; + + if (readb(&hdr->cli_error_os) != 0) { + /* we are in an error msg throttling state; come out of it */ + pr_info("%s Channel OS client error state cleared\n", id); + writeb(0, &hdr->cli_error_os); + } + if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) + return; + if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) { + pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n", + id, ULTRA_CHANNELCLI_STRING( + readl(&hdr->cli_state_os)), + readl(&hdr->cli_state_os)); + /* return; */ + } + writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* release busy */ +} + +/* +* Routine Description: +* Tries to insert the prebuilt signal pointed to by pSignal into the nth +* Queue of the Channel pointed to by pChannel +* +* Parameters: +* pChannel: (IN) points to the IO Channel +* Queue: (IN) nth Queue of the IO Channel +* pSignal: (IN) pointer to the signal +* +* Assumptions: +* - pChannel, Queue and pSignal are valid. +* - If insertion fails due to a full queue, the caller will determine the +* retry policy (e.g. wait & try again, report an error, etc.). +* +* Return value: 1 if the insertion succeeds, 0 if the queue was +* full. +*/ + +unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, + void *sig); + +/* +* Routine Description: +* Removes one signal from Channel pChannel's nth Queue at the +* time of the call and copies it into the memory pointed to by +* pSignal. +* +* Parameters: +* pChannel: (IN) points to the IO Channel +* Queue: (IN) nth Queue of the IO Channel +* pSignal: (IN) pointer to where the signals are to be copied +* +* Assumptions: +* - pChannel and Queue are valid. +* - pSignal points to a memory area large enough to hold queue's SignalSize +* +* Return value: 1 if the removal succeeds, 0 if the queue was +* empty. +*/ + +unsigned char spar_signal_remove(struct channel_header __iomem *ch, u32 queue, + void *sig); + +/* +* Routine Description: +* Removes all signals present in Channel pChannel's nth Queue at the +* time of the call and copies them into the memory pointed to by +* pSignal. Returns the # of signals copied as the value of the routine. +* +* Parameters: +* pChannel: (IN) points to the IO Channel +* Queue: (IN) nth Queue of the IO Channel +* pSignal: (IN) pointer to where the signals are to be copied +* +* Assumptions: +* - pChannel and Queue are valid. +* - pSignal points to a memory area large enough to hold Queue's MaxSignals +* # of signals, each of which is Queue's SignalSize. +* +* Return value: +* # of signals copied. +*/ +unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, + void *sig); + +/* +* Routine Description: +* Determine whether a signal queue is empty. +* +* Parameters: +* pChannel: (IN) points to the IO Channel +* Queue: (IN) nth Queue of the IO Channel +* +* Return value: +* 1 if the signal queue is empty, 0 otherwise. +*/ +unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, + u32 queue); + +#endif diff --git a/drivers/staging/unisys/include/channel_guid.h b/drivers/staging/unisys/include/channel_guid.h new file mode 100644 index 0000000..706363fc --- /dev/null +++ b/drivers/staging/unisys/include/channel_guid.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +/* + * CHANNEL Guids + */ + +/* Used in IOChannel + * {414815ed-c58c-11da-95a9-00e08161165f} + */ +#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x414815ed, 0xc58c, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) +static const uuid_le spar_vhba_channel_protocol_uuid = + SPAR_VHBA_CHANNEL_PROTOCOL_UUID; + +/* Used in IOChannel + * {8cd5994d-c58e-11da-95a9-00e08161165f} + */ +#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) +static const uuid_le spar_vnic_channel_protocol_uuid = + SPAR_VNIC_CHANNEL_PROTOCOL_UUID; + +/* Used in IOChannel + * {72120008-4AAB-11DC-8530-444553544200} + */ +#define SPAR_SIOVM_UUID \ + UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ + 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) +static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; + +/* Used in visornoop/visornoop_main.c + * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} + */ +#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ + 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) + +static const uuid_le spar_controldirector_channel_protocol_uuid = + SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; + +/* Used in visorchipset/visorchipset_main.c + * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C} + */ +#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ + 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h new file mode 100644 index 0000000..a50d9cf --- /dev/null +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -0,0 +1,485 @@ +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __CONTROLVMCHANNEL_H__ +#define __CONTROLVMCHANNEL_H__ + +#include <linux/uuid.h> +#include "channel.h" + +/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */ +#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \ + 0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d) + +#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE \ + ULTRA_CHANNEL_PROTOCOL_SIGNATURE +#define CONTROLVM_MESSAGE_MAX 64 + +/* Must increment this whenever you insert or delete fields within + * this channel struct. Also increment whenever you change the meaning + * of fields within this channel struct so as to break pre-existing + * software. Note that you can usually add fields to the END of the + * channel struct withOUT needing to increment this. + */ +#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID 1 + +#define SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch) \ + spar_check_channel_client(ch, \ + SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \ + "controlvm", \ + sizeof(struct spar_controlvm_channel_protocol), \ + ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \ + ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE) + +#define MAX_SERIAL_NUM 32 + +/* Defines for various channel queues */ +#define CONTROLVM_QUEUE_REQUEST 0 +#define CONTROLVM_QUEUE_RESPONSE 1 +#define CONTROLVM_QUEUE_EVENT 2 +#define CONTROLVM_QUEUE_ACK 3 + +/* Max num of messages stored during IOVM creation to be reused after crash */ +#define CONTROLVM_CRASHMSG_MAX 2 + +struct spar_segment_state { + u16 enabled:1; /* Bit 0: May enter other states */ + u16 active:1; /* Bit 1: Assigned to active partition */ + u16 alive:1; /* Bit 2: Configure message sent to + * service/server */ + u16 revoked:1; /* Bit 3: similar to partition state + * ShuttingDown */ + u16 allocated:1; /* Bit 4: memory (device/port number) + * has been selected by Command */ + u16 known:1; /* Bit 5: has been introduced to the + * service/guest partition */ + u16 ready:1; /* Bit 6: service/Guest partition has + * responded to introduction */ + u16 operating:1; /* Bit 7: resource is configured and + * operating */ + /* Note: don't use high bit unless we need to switch to ushort + * which is non-compliant */ +}; + +static const struct spar_segment_state segment_state_running = { + 1, 1, 1, 0, 1, 1, 1, 1 +}; + +static const struct spar_segment_state segment_state_paused = { + 1, 1, 1, 0, 1, 1, 1, 0 +}; + +static const struct spar_segment_state segment_state_standby = { + 1, 1, 0, 0, 1, 1, 1, 0 +}; + +/* Ids for commands that may appear in either queue of a ControlVm channel. + * + * Commands that are initiated by the command partition (CP), by an IO or + * console service partition (SP), or by a guest partition (GP)are: + * - issued on the RequestQueue queue (q #0) in the ControlVm channel + * - responded to on the ResponseQueue queue (q #1) in the ControlVm channel + * + * Events that are initiated by an IO or console service partition (SP) or + * by a guest partition (GP) are: + * - issued on the EventQueue queue (q #2) in the ControlVm channel + * - responded to on the EventAckQueue queue (q #3) in the ControlVm channel + */ +enum controlvm_id { + CONTROLVM_INVALID = 0, + /* SWITCH commands required Parameter: SwitchNumber */ + /* BUS commands required Parameter: BusNumber */ + CONTROLVM_BUS_CREATE = 0x101, /* CP --> SP, GP */ + CONTROLVM_BUS_DESTROY = 0x102, /* CP --> SP, GP */ + CONTROLVM_BUS_CONFIGURE = 0x104, /* CP --> SP */ + CONTROLVM_BUS_CHANGESTATE = 0x105, /* CP --> SP, GP */ + CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106, /* SP, GP --> CP */ +/* DEVICE commands required Parameter: BusNumber, DeviceNumber */ + + CONTROLVM_DEVICE_CREATE = 0x201, /* CP --> SP, GP */ + CONTROLVM_DEVICE_DESTROY = 0x202, /* CP --> SP, GP */ + CONTROLVM_DEVICE_CONFIGURE = 0x203, /* CP --> SP */ + CONTROLVM_DEVICE_CHANGESTATE = 0x204, /* CP --> SP, GP */ + CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205, /* SP, GP --> CP */ + CONTROLVM_DEVICE_RECONFIGURE = 0x206, /* CP --> Boot */ +/* CHIPSET commands */ + CONTROLVM_CHIPSET_INIT = 0x301, /* CP --> SP, GP */ + CONTROLVM_CHIPSET_STOP = 0x302, /* CP --> SP, GP */ + CONTROLVM_CHIPSET_READY = 0x304, /* CP --> SP */ + CONTROLVM_CHIPSET_SELFTEST = 0x305, /* CP --> SP */ + +}; + +struct irq_info { + u64 reserved1; + + /* specifies interrupt handle. It is used to retrieve the + * corresponding interrupt pin from Monitor; and the + * interrupt pin is used to connect to the corresponding + * interrupt. Used by IOPart-GP only. + */ + u64 recv_irq_handle; + + /* specifies interrupt vector. It, interrupt pin, and shared are + * used to connect to the corresponding interrupt. Used by + * IOPart-GP only. + */ + u32 recv_irq_vector; + + /* specifies if the recvInterrupt is shared. It, interrupt pin + * and vector are used to connect to 0 = not shared; 1 = shared. + * the corresponding interrupt. Used by IOPart-GP only. + */ + u8 recv_irq_shared; + u8 reserved[3]; /* Natural alignment purposes */ +}; + +struct pci_id { + u16 domain; + u8 bus; + u8 slot; + u8 func; + u8 reserved[3]; /* Natural alignment purposes */ +}; + +struct efi_spar_indication { + u64 boot_to_fw_ui:1; /* Bit 0: Stop in uefi ui */ + u64 clear_nvram:1; /* Bit 1: Clear NVRAM */ + u64 clear_cmos:1; /* Bit 2: Clear CMOS */ + u64 boot_to_tool:1; /* Bit 3: Run install tool */ + /* remaining bits are available */ +}; + +enum ultra_chipset_feature { + ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001, + ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002, +}; + +/* This is the common structure that is at the beginning of every + * ControlVm message (both commands and responses) in any ControlVm + * queue. Commands are easily distinguished from responses by + * looking at the flags.response field. + */ +struct controlvm_message_header { + u32 id; /* See CONTROLVM_ID. */ + /* For requests, indicates the message type. */ + /* For responses, indicates the type of message we are responding to. */ + + u32 message_size; /* Includes size of this struct + size + * of message */ + u32 segment_index; /* Index of segment containing Vm + * message/information */ + u32 completion_status; /* Error status code or result of + * message completion */ + struct { + u32 failed:1; /* =1 in a response to * signify + * failure */ + u32 response_expected:1; /* =1 in all messages that expect a + * response (Control ignores this + * bit) */ + u32 server:1; /* =1 in all bus & device-related + * messages where the message + * receiver is to act as the bus or + * device server */ + u32 test_message:1; /* =1 for testing use only + * (Control and Command ignore this + * bit) */ + u32 partial_completion:1; /* =1 if there are forthcoming + * responses/acks associated + * with this message */ + u32 preserve:1; /* =1 this is to let us know to + * preserve channel contents + * (for running guests)*/ + u32 writer_in_diag:1; /* =1 the DiagWriter is active in the + * Diagnostic Partition*/ + } flags; + u32 reserved; /* Natural alignment */ + u64 message_handle; /* Identifies the particular message instance, + * and is used to match particular */ + /* request instances with the corresponding response instance. */ + u64 payload_vm_offset; /* Offset of payload area from start of this + * instance of ControlVm segment */ + u32 payload_max_bytes; /* Maximum bytes allocated in payload + * area of ControlVm segment */ + u32 payload_bytes; /* Actual number of bytes of payload + * area to copy between IO/Command; */ + /* if non-zero, there is a payload to copy. */ +}; + +struct controlvm_packet_device_create { + u32 bus_no; /* bus # (0..n-1) from the msg receiver's end */ + u32 dev_no; /* bus-relative (0..n-1) device number */ + u64 channel_addr; /* Guest physical address of the channel, which + * can be dereferenced by the receiver of this + * ControlVm command */ + u64 channel_bytes; /* specifies size of the channel in bytes */ + uuid_le data_type_uuid; /* specifies format of data in channel */ + uuid_le dev_inst_uuid; /* instance guid for the device */ + struct irq_info intr; /* specifies interrupt information */ +}; /* for CONTROLVM_DEVICE_CREATE */ + +struct controlvm_packet_device_configure { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + /* Control uses header SegmentIndex field to access bus number... */ + u32 dev_no; /* bus-relative (0..n-1) device number */ +} ; /* for CONTROLVM_DEVICE_CONFIGURE */ + +struct controlvm_message_device_create { + struct controlvm_message_header header; + struct controlvm_packet_device_create packet; +}; /* total 128 bytes */ + +struct controlvm_message_device_configure { + struct controlvm_message_header header; + struct controlvm_packet_device_configure packet; +}; /* total 56 bytes */ + +/* This is the format for a message in any ControlVm queue. */ +struct controlvm_message_packet { + union { + struct { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + u32 dev_count; /* indicates the max number of + * devices on this bus */ + u64 channel_addr; /* Guest physical address of + * the channel, which can be + * dereferenced by the receiver + * of this ControlVm command */ + u64 channel_bytes; /* size of the channel */ + uuid_le bus_data_type_uuid; /* indicates format of + * data in bus channel*/ + uuid_le bus_inst_uuid; /* instance uuid for the bus */ + } create_bus; /* for CONTROLVM_BUS_CREATE */ + struct { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + u32 reserved; /* Natural alignment purposes */ + } destroy_bus; /* for CONTROLVM_BUS_DESTROY */ + struct { + u32 bus_no; /* bus # (0..n-1) from the receiver's + * perspective */ + u32 reserved1; /* for alignment purposes */ + u64 guest_handle; /* This is used to convert + * guest physical address to + * physical address */ + u64 recv_bus_irq_handle; + /* specifies interrupt info. It is used by SP + * to register to receive interrupts from the + * CP. This interrupt is used for bus level + * notifications. The corresponding + * sendBusInterruptHandle is kept in CP. */ + } configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ + /* for CONTROLVM_DEVICE_CREATE */ + struct controlvm_packet_device_create create_device; + struct { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + u32 dev_no; /* bus-relative (0..n-1) device # */ + } destroy_device; /* for CONTROLVM_DEVICE_DESTROY */ + /* for CONTROLVM_DEVICE_CONFIGURE */ + struct controlvm_packet_device_configure configure_device; + struct { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + u32 dev_no; /* bus-relative (0..n-1) device # */ + } reconfigure_device; /* for CONTROLVM_DEVICE_RECONFIGURE */ + struct { + u32 bus_no; + struct spar_segment_state state; + u8 reserved[2]; /* Natural alignment purposes */ + } bus_change_state; /* for CONTROLVM_BUS_CHANGESTATE */ + struct { + u32 bus_no; + u32 dev_no; + struct spar_segment_state state; + struct { + u32 phys_device:1; /* =1 if message is for + * a physical device */ + } flags; + u8 reserved[2]; /* Natural alignment purposes */ + } device_change_state; /* for CONTROLVM_DEVICE_CHANGESTATE */ + struct { + u32 bus_no; + u32 dev_no; + struct spar_segment_state state; + u8 reserved[6]; /* Natural alignment purposes */ + } device_change_state_event; + /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */ + struct { + u32 bus_count; /* indicates the max number of busses */ + u32 switch_count; /* indicates the max number of + * switches if a service partition */ + enum ultra_chipset_feature features; + u32 platform_number; /* Platform Number */ + } init_chipset; /* for CONTROLVM_CHIPSET_INIT */ + struct { + u32 options; /* reserved */ + u32 test; /* bit 0 set to run embedded selftest */ + } chipset_selftest; /* for CONTROLVM_CHIPSET_SELFTEST */ + u64 addr; /* a physical address of something, that can be + * dereferenced by the receiver of this + * ControlVm command (depends on command id) */ + u64 handle; /* a handle of something (depends on command + * id) */ + }; +}; + +/* All messages in any ControlVm queue have this layout. */ +struct controlvm_message { + struct controlvm_message_header hdr; + struct controlvm_message_packet cmd; +}; + +struct spar_controlvm_channel_protocol { + struct channel_header header; + u64 gp_controlvm; /* guest phys addr of this channel */ + u64 gp_partition_tables;/* guest phys addr of partition tables */ + u64 gp_diag_guest; /* guest phys addr of diagnostic channel */ + u64 gp_boot_romdisk;/* guest phys addr of (read* only) Boot ROM disk */ + u64 gp_boot_ramdisk;/* guest phys addr of writable Boot RAM disk */ + u64 gp_acpi_table; /* guest phys addr of acpi table */ + u64 gp_control_channel;/* guest phys addr of control channel */ + u64 gp_diag_romdisk;/* guest phys addr of diagnostic ROM disk */ + u64 gp_nvram; /* guest phys addr of NVRAM channel */ + u64 request_payload_offset; /* Offset to request payload area */ + u64 event_payload_offset; /* Offset to event payload area */ + u32 request_payload_bytes; /* Bytes available in request payload + * area */ + u32 event_payload_bytes;/* Bytes available in event payload area */ + u32 control_channel_bytes; + u32 nvram_channel_bytes; /* Bytes in PartitionNvram segment */ + u32 message_bytes; /* sizeof(CONTROLVM_MESSAGE) */ + u32 message_count; /* CONTROLVM_MESSAGE_MAX */ + u64 gp_smbios_table; /* guest phys addr of SMBIOS tables */ + u64 gp_physical_smbios_table; /* guest phys addr of SMBIOS table */ + /* ULTRA_MAX_GUESTS_PER_SERVICE */ + char gp_reserved[2688]; + + /* guest physical address of EFI firmware image base */ + u64 virtual_guest_firmware_image_base; + + /* guest physical address of EFI firmware entry point */ + u64 virtual_guest_firmware_entry_point; + + /* guest EFI firmware image size */ + u64 virtual_guest_firmware_image_size; + + /* GPA = 1MB where EFI firmware image is copied to */ + u64 virtual_guest_firmware_boot_base; + u64 virtual_guest_image_base; + u64 virtual_guest_image_size; + u64 prototype_control_channel_offset; + u64 virtual_guest_partition_handle; + + u16 restore_action; /* Restore Action field to restore the guest + * partition */ + u16 dump_action; /* For Windows guests it shows if the visordisk + * is running in dump mode */ + u16 nvram_fail_count; + u16 saved_crash_message_count; /* = CONTROLVM_CRASHMSG_MAX */ + u32 saved_crash_message_offset; /* Offset to request payload area needed + * for crash dump */ + u32 installation_error; /* Type of error encountered during + * installation */ + u32 installation_text_id; /* Id of string to display */ + u16 installation_remaining_steps;/* Number of remaining installation + * steps (for progress bars) */ + u8 tool_action; /* ULTRA_TOOL_ACTIONS Installation Action + * field */ + u8 reserved; /* alignment */ + struct efi_spar_indication efi_spar_ind; + struct efi_spar_indication efi_spar_ind_supported; + u32 sp_reserved; + u8 reserved2[28]; /* Force signals to begin on 128-byte cache + * line */ + struct signal_queue_header request_queue;/* Service or guest partition + * uses this queue to send + * requests to Control */ + struct signal_queue_header response_queue;/* Control uses this queue to + * respond to service or guest + * partition requests */ + struct signal_queue_header event_queue; /* Control uses this queue to + * send events to service or + * guest partition */ + struct signal_queue_header event_ack_queue;/* Service or guest partition + * uses this queue to ack + * Control events */ + + /* Request fixed-size message pool - does not include payload */ + struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX]; + + /* Response fixed-size message pool - does not include payload */ + struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX]; + + /* Event fixed-size message pool - does not include payload */ + struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX]; + + /* Ack fixed-size message pool - does not include payload */ + struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX]; + + /* Message stored during IOVM creation to be reused after crash */ + struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX]; +}; + +/* Offsets for VM channel attributes */ +#define VM_CH_REQ_QUEUE_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, request_queue) +#define VM_CH_RESP_QUEUE_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, response_queue) +#define VM_CH_EVENT_QUEUE_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, event_queue) +#define VM_CH_ACK_QUEUE_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, event_ack_queue) +#define VM_CH_REQ_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, request_msg) +#define VM_CH_RESP_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, response_msg) +#define VM_CH_EVENT_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, event_msg) +#define VM_CH_ACK_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, event_ack_msg) +#define VM_CH_CRASH_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, saved_crash_msg) + +/* The following header will be located at the beginning of PayloadVmOffset for + * various ControlVm commands. The receiver of a ControlVm command with a + * PayloadVmOffset will dereference this address and then use connection_offset, + * initiator_offset, and target_offset to get the location of UTF-8 formatted + * strings that can be parsed to obtain command-specific information. The value + * of total_length should equal PayloadBytes. The format of the strings at + * PayloadVmOffset will take different forms depending on the message. + */ +struct spar_controlvm_parameters_header { + u32 total_length; + u32 header_length; + u32 connection_offset; + u32 connection_length; + u32 initiator_offset; + u32 initiator_length; + u32 target_offset; + u32 target_length; + u32 client_offset; + u32 client_length; + u32 name_offset; + u32 name_length; + uuid_le id; + u32 revision; + u32 reserved; /* Natural alignment */ +}; + +#endif /* __CONTROLVMCHANNEL_H__ */ -- 2.1.4 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel