Message ID | 20221105034228.1376677-1-david.e.box@linux.intel.com (mailing list archive) |
---|---|
State | Accepted, archived |
Headers | show |
Series | platform/x86/intel/pmt: Sapphire Rapids PMT errata fix | expand |
Hi, On 11/5/22 04:42, David E. Box wrote: > On Sapphire Rapids, due to a hardware issue affecting the PUNIT telemetry > region, reads that are not done in QWORD quantities and alignment may > return incorrect data. Use a custom 64-bit copy for this region. > > Signed-off-by: David E. Box <david.e.box@linux.intel.com> Thank you for your patch, I've applied this patch to my review-hans branch: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans Note it will show up in my review-hans branch once I've pushed my local branch there, which might take a while. Once I've run some tests on this branch the patches there will be added to the platform-drivers-x86/for-next branch and eventually will be included in the pdx86 pull-request to Linus for the next merge-window. Regards, Hans > --- > drivers/platform/x86/intel/pmt/class.c | 31 +++++++++++++++++++++++++- > 1 file changed, 30 insertions(+), 1 deletion(-) > > diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c > index 53d7fd2943b4..46598dcb634a 100644 > --- a/drivers/platform/x86/intel/pmt/class.c > +++ b/drivers/platform/x86/intel/pmt/class.c > @@ -9,6 +9,7 @@ > */ > > #include <linux/kernel.h> > +#include <linux/io-64-nonatomic-lo-hi.h> > #include <linux/module.h> > #include <linux/mm.h> > #include <linux/pci.h> > @@ -19,6 +20,7 @@ > #define PMT_XA_START 0 > #define PMT_XA_MAX INT_MAX > #define PMT_XA_LIMIT XA_LIMIT(PMT_XA_START, PMT_XA_MAX) > +#define GUID_SPR_PUNIT 0x9956f43f > > bool intel_pmt_is_early_client_hw(struct device *dev) > { > @@ -33,6 +35,29 @@ bool intel_pmt_is_early_client_hw(struct device *dev) > } > EXPORT_SYMBOL_GPL(intel_pmt_is_early_client_hw); > > +static inline int > +pmt_memcpy64_fromio(void *to, const u64 __iomem *from, size_t count) > +{ > + int i, remain; > + u64 *buf = to; > + > + if (!IS_ALIGNED((unsigned long)from, 8)) > + return -EFAULT; > + > + for (i = 0; i < count/8; i++) > + buf[i] = readq(&from[i]); > + > + /* Copy any remaining bytes */ > + remain = count % 8; > + if (remain) { > + u64 tmp = readq(&from[i]); > + > + memcpy(&buf[i], &tmp, remain); > + } > + > + return count; > +} > + > /* > * sysfs > */ > @@ -54,7 +79,11 @@ intel_pmt_read(struct file *filp, struct kobject *kobj, > if (count > entry->size - off) > count = entry->size - off; > > - memcpy_fromio(buf, entry->base + off, count); > + if (entry->guid == GUID_SPR_PUNIT) > + /* PUNIT on SPR only supports aligned 64-bit read */ > + count = pmt_memcpy64_fromio(buf, entry->base + off, count); > + else > + memcpy_fromio(buf, entry->base + off, count); > > return count; > } > > base-commit: 225469d4acbcb873358d7618bad6e0203b67b964
diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c index 53d7fd2943b4..46598dcb634a 100644 --- a/drivers/platform/x86/intel/pmt/class.c +++ b/drivers/platform/x86/intel/pmt/class.c @@ -9,6 +9,7 @@ */ #include <linux/kernel.h> +#include <linux/io-64-nonatomic-lo-hi.h> #include <linux/module.h> #include <linux/mm.h> #include <linux/pci.h> @@ -19,6 +20,7 @@ #define PMT_XA_START 0 #define PMT_XA_MAX INT_MAX #define PMT_XA_LIMIT XA_LIMIT(PMT_XA_START, PMT_XA_MAX) +#define GUID_SPR_PUNIT 0x9956f43f bool intel_pmt_is_early_client_hw(struct device *dev) { @@ -33,6 +35,29 @@ bool intel_pmt_is_early_client_hw(struct device *dev) } EXPORT_SYMBOL_GPL(intel_pmt_is_early_client_hw); +static inline int +pmt_memcpy64_fromio(void *to, const u64 __iomem *from, size_t count) +{ + int i, remain; + u64 *buf = to; + + if (!IS_ALIGNED((unsigned long)from, 8)) + return -EFAULT; + + for (i = 0; i < count/8; i++) + buf[i] = readq(&from[i]); + + /* Copy any remaining bytes */ + remain = count % 8; + if (remain) { + u64 tmp = readq(&from[i]); + + memcpy(&buf[i], &tmp, remain); + } + + return count; +} + /* * sysfs */ @@ -54,7 +79,11 @@ intel_pmt_read(struct file *filp, struct kobject *kobj, if (count > entry->size - off) count = entry->size - off; - memcpy_fromio(buf, entry->base + off, count); + if (entry->guid == GUID_SPR_PUNIT) + /* PUNIT on SPR only supports aligned 64-bit read */ + count = pmt_memcpy64_fromio(buf, entry->base + off, count); + else + memcpy_fromio(buf, entry->base + off, count); return count; }
On Sapphire Rapids, due to a hardware issue affecting the PUNIT telemetry region, reads that are not done in QWORD quantities and alignment may return incorrect data. Use a custom 64-bit copy for this region. Signed-off-by: David E. Box <david.e.box@linux.intel.com> --- drivers/platform/x86/intel/pmt/class.c | 31 +++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) base-commit: 225469d4acbcb873358d7618bad6e0203b67b964