aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@nutanix.com>2021-04-23 17:51:10 +0100
committerGitHub <noreply@github.com>2021-04-23 17:51:10 +0100
commit13e3f8d38bc23c2a95654c46addea84ca6de365a (patch)
tree302018fdfde5724854b8a0ad7efe6805ff933c6c
parentf8e47df6b874fb8a5f06089512820e3e8c8a6c4a (diff)
downloadlibvfio-user-13e3f8d38bc23c2a95654c46addea84ca6de365a.zip
libvfio-user-13e3f8d38bc23c2a95654c46addea84ca6de365a.tar.gz
libvfio-user-13e3f8d38bc23c2a95654c46addea84ca6de365a.tar.bz2
correct PM capability definition (#452)
the static size assert for the PMCS register was checking the wrong struct; however, the struct was nonetheless 4 bytes long, due to uint bitfields. This accidentally meant the containing struct pmcap was the correct size (the alignment attribute makes no difference). After fixing struct pmcs, we'll include the additional two bytes defined in the PCI PM specification, Section 3.2. These are "optional", but as elsewhere, we'll require them when adding the capability. Signed-off-by: John Levon <john.levon@nutanix.com> Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
-rw-r--r--include/pci_caps/pm.h30
-rw-r--r--lib/pci_caps.c15
2 files changed, 33 insertions, 12 deletions
diff --git a/include/pci_caps/pm.h b/include/pci_caps/pm.h
index 6daa812..00f8889 100644
--- a/include/pci_caps/pm.h
+++ b/include/pci_caps/pm.h
@@ -39,6 +39,9 @@
extern "C" {
#endif
+/*
+ * Power Management Capabilities Register
+ */
struct pc {
unsigned int vs:3;
unsigned int pmec:1;
@@ -51,29 +54,34 @@ struct pc {
} __attribute__((packed));
_Static_assert(sizeof(struct pc) == 0x2, "bad PC size");
+/*
+ * Power Management Status and Control Register
+ */
struct pmcs {
union {
uint16_t raw;
struct {
- unsigned int ps:2;
- unsigned int res1:1;
- unsigned int nsfrst:1;
- unsigned int res2:4;
- unsigned int pmee:1;
- unsigned int dse:4;
- unsigned int dsc:2;
- unsigned int pmes:1;
+ unsigned short ps:2;
+ unsigned short res1:1;
+ unsigned short nsfrst:1;
+ unsigned short res2:4;
+ unsigned short pmee:1;
+ unsigned short dse:4;
+ unsigned short dsc:2;
+ unsigned short pmes:1;
};
};
} __attribute__((packed));
-_Static_assert(sizeof(struct pc) == 0x2, "bad PMCS size");
+_Static_assert(sizeof(struct pmcs) == 0x2, "bad PMCS size");
struct pmcap {
struct cap_hdr hdr;
struct pc pc;
struct pmcs pmcs;
-} __attribute__((packed)) __attribute__ ((aligned(8))); /* FIXME why does it need to be aligned? */
-_Static_assert(sizeof(struct pmcap) == PCI_PM_SIZEOF, "bad PC size");
+ uint8_t pmcsr_bse;
+ uint8_t data;
+} __attribute__((packed));
+_Static_assert(sizeof(struct pmcap) == PCI_PM_SIZEOF, "bad pmcap size");
_Static_assert(offsetof(struct pmcap, hdr) == 0, "bad offset");
#ifdef __cplusplus
diff --git a/lib/pci_caps.c b/lib/pci_caps.c
index 50b1ec3..8ed5643 100644
--- a/lib/pci_caps.c
+++ b/lib/pci_caps.c
@@ -141,7 +141,7 @@ cap_write_pm(vfu_ctx_t *vfu_ctx, struct pci_cap *cap, char * buf,
if (count != sizeof(struct pc)) {
return ERROR_INT(EINVAL);
}
- vfu_log(vfu_ctx, LOG_ERR, "FIXME: write to pmcp::pc unimplemented");
+ vfu_log(vfu_ctx, LOG_ERR, "FIXME: write to pmcap::pc unimplemented");
return ERROR_INT(ENOTSUP);
case offsetof(struct pmcap, pmcs):
if (count != sizeof(struct pmcs)) {
@@ -149,6 +149,19 @@ cap_write_pm(vfu_ctx_t *vfu_ctx, struct pci_cap *cap, char * buf,
}
handle_pmcs_write(vfu_ctx, pm, (struct pmcs *)buf);
return sizeof(struct pmcs);
+ case offsetof(struct pmcap, pmcsr_bse):
+ if (count != 1) {
+ return ERROR_INT(EINVAL);
+ }
+ vfu_log(vfu_ctx, LOG_ERR,
+ "FIXME: write to pmcap::pmcsr_bse unimplemented");
+ return ERROR_INT(ENOTSUP);
+ case offsetof(struct pmcap, data):
+ if (count != 1) {
+ return ERROR_INT(EINVAL);
+ }
+ vfu_log(vfu_ctx, LOG_ERR, "FIXME: write to pmcap::data unimplemented");
+ return ERROR_INT(ENOTSUP);
}
return ERROR_INT(EINVAL);
}