aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers/net/ena.h
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2022-08-26 13:37:23 +0100
committerMichael Brown <mcb30@ipxe.org>2022-08-26 19:38:27 +0100
commit3b81a4e2568cfca50893095638a03069785cd33e (patch)
treebc36cba7cac5a1b11c165441821724104b76facb /src/drivers/net/ena.h
parent9f81e97af5e3861ea2d0ad7b11f2c8746c2c52f9 (diff)
downloadipxe-3b81a4e2568cfca50893095638a03069785cd33e.tar.gz
[ena] Provide a host information page
Some versions of the ENA firmware (observed on a c6i.large instance in eu-west-2) seem to require a host information page, without which the CREATE_CQ command will fail with ENA_ADMIN_UNKNOWN_ERROR. These firmware versions also seem to require us to claim that we are a Linux kernel with a specific driver major version number. This appears to be a firmware bug, as revealed by Linux kernel commit 1a63443af ("net/amazon: Ensure that driver version is aligned to the linux kernel"): this commit changed the value of the driver version number field to be the Linux kernel version, and was hastily reverted in commit 92040c6da ("net: ena: fix broken interface between ENA driver and FW") which clarified that the version number field does actually have some undocumented significance to some versions of the firmware. Fix by providing a host information page via the SET_FEATURE command, incorporating the apparently necessary lies about our identity. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/ena.h')
-rw-r--r--src/drivers/net/ena.h101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/drivers/net/ena.h b/src/drivers/net/ena.h
index 78693e678..cbee1e768 100644
--- a/src/drivers/net/ena.h
+++ b/src/drivers/net/ena.h
@@ -127,10 +127,86 @@ struct ena_device_attributes {
uint32_t mtu;
} __attribute__ (( packed ));
+/** Host attributes */
+#define ENA_HOST_ATTRIBUTES 28
+
+/** Host attributes */
+struct ena_host_attributes {
+ /** Host info base address */
+ uint64_t info;
+ /** Debug area base address */
+ uint64_t debug;
+ /** Debug area size */
+ uint32_t debug_len;
+} __attribute__ (( packed ));
+
+/** Host information */
+struct ena_host_info {
+ /** Operating system type */
+ uint32_t type;
+ /** Operating system distribution (string) */
+ char dist_str[128];
+ /** Operating system distribution (numeric) */
+ uint32_t dist;
+ /** Kernel version (string) */
+ char kernel_str[32];
+ /** Kernel version (numeric) */
+ uint32_t kernel;
+ /** Driver version */
+ uint32_t version;
+ /** Linux network device features */
+ uint64_t linux_features;
+ /** ENA specification version */
+ uint16_t spec;
+ /** PCI bus:dev.fn address */
+ uint16_t busdevfn;
+ /** Number of CPUs */
+ uint16_t cpus;
+ /** Reserved */
+ uint8_t reserved_a[2];
+ /** Supported features */
+ uint32_t features;
+} __attribute__ (( packed ));
+
+/** Linux operating system type
+ *
+ * There is a defined "iPXE" operating system type (with value 5).
+ * However, some very broken versions of the ENA firmware will refuse
+ * to allow a completion queue to be created if the "iPXE" type is
+ * used.
+ */
+#define ENA_HOST_INFO_TYPE_LINUX 1
+
+/** Driver version
+ *
+ * The driver version field is nominally used to report a version
+ * number outside of the VM for consumption by humans (and potentially
+ * by automated monitoring tools that could e.g. check for outdated
+ * versions with known security flaws).
+ *
+ * However, at some point in the development of the ENA firmware, some
+ * unknown person at AWS thought it would be sensible to apply a
+ * machine interpretation to this field and adjust the behaviour of
+ * the firmware based on its value, thereby creating a maintenance and
+ * debugging nightmare for all existing and future drivers.
+ *
+ * Hint to engineers: if you ever find yourself writing code of the
+ * form "if (version == SOME_MAGIC_NUMBER)" then something has gone
+ * very, very wrong. This *always* indicates that something is
+ * broken, either in your own code or in the code with which you are
+ * forced to interact.
+ */
+#define ENA_HOST_INFO_VERSION_WTF 0x00000002UL
+
+/** ENA specification version */
+#define ENA_HOST_INFO_SPEC_2_0 0x0200
+
/** Feature */
union ena_feature {
/** Device attributes */
struct ena_device_attributes device;
+ /** Host attributes */
+ struct ena_host_attributes host;
};
/** Submission queue direction */
@@ -300,6 +376,27 @@ struct ena_get_feature_rsp {
union ena_feature feature;
} __attribute__ (( packed ));
+/** Set feature */
+#define ENA_SET_FEATURE 9
+
+/** Set feature request */
+struct ena_set_feature_req {
+ /** Header */
+ struct ena_aq_header header;
+ /** Length */
+ uint32_t len;
+ /** Address */
+ uint64_t address;
+ /** Flags */
+ uint8_t flags;
+ /** Feature identifier */
+ uint8_t id;
+ /** Reserved */
+ uint8_t reserved[2];
+ /** Feature */
+ union ena_feature feature;
+} __attribute__ (( packed ));
+
/** Get statistics */
#define ENA_GET_STATS 11
@@ -360,6 +457,8 @@ union ena_aq_req {
struct ena_destroy_cq_req destroy_cq;
/** Get feature */
struct ena_get_feature_req get_feature;
+ /** Set feature */
+ struct ena_set_feature_req set_feature;
/** Get statistics */
struct ena_get_stats_req get_stats;
/** Padding */
@@ -590,6 +689,8 @@ struct ena_qp {
struct ena_nic {
/** Registers */
void *regs;
+ /** Host info */
+ struct ena_host_info *info;
/** Admin queue */
struct ena_aq aq;
/** Admin completion queue */