[PATCH 05/11] RISC-V: drivers/iommu/riscv: Add sysfs interface

Tomasz Jeznach tjeznach at rivosinc.com
Thu Jul 20 10:47:40 PDT 2023


On Thu, Jul 20, 2023 at 5:51 AM Baolu Lu <baolu.lu at linux.intel.com> wrote:
>
> On 2023/7/20 3:33, Tomasz Jeznach wrote:
> > +#define sysfs_dev_to_iommu(dev) \
> > +     container_of(dev_get_drvdata(dev), struct riscv_iommu_device, iommu)
> > +
> > +static ssize_t address_show(struct device *dev,
> > +                         struct device_attribute *attr, char *buf)
> > +{
> > +     struct riscv_iommu_device *iommu = sysfs_dev_to_iommu(dev);
> > +     return sprintf(buf, "%llx\n", iommu->reg_phys);
>
> Use sysfs_emit() please.
>

ack. Thanks, will update.

> > +}
> > +
> > +static DEVICE_ATTR_RO(address);
> > +
> > +#define ATTR_RD_REG32(name, offset)                                  \
> > +     ssize_t reg_ ## name ## _show(struct device *dev,               \
> > +                     struct device_attribute *attr, char *buf)       \
> > +{                                                                    \
> > +     struct riscv_iommu_device *iommu = sysfs_dev_to_iommu(dev);     \
> > +     return sprintf(buf, "0x%x\n",                                   \
> > +                     riscv_iommu_readl(iommu, offset));              \
> > +}
> > +
> > +#define ATTR_RD_REG64(name, offset)                                  \
> > +     ssize_t reg_ ## name ## _show(struct device *dev,               \
> > +                     struct device_attribute *attr, char *buf)       \
> > +{                                                                    \
> > +     struct riscv_iommu_device *iommu = sysfs_dev_to_iommu(dev);     \
> > +     return sprintf(buf, "0x%llx\n",                                 \
> > +                     riscv_iommu_readq(iommu, offset));              \
> > +}
> > +
> > +#define ATTR_WR_REG32(name, offset)                                  \
> > +     ssize_t reg_ ## name ## _store(struct device *dev,              \
> > +                     struct device_attribute *attr,                  \
> > +                     const char *buf, size_t len)                    \
> > +{                                                                    \
> > +     struct riscv_iommu_device *iommu = sysfs_dev_to_iommu(dev);     \
> > +     unsigned long val;                                              \
> > +     int ret;                                                        \
> > +     ret = kstrtoul(buf, 0, &val);                                   \
> > +     if (ret)                                                        \
> > +             return ret;                                             \
> > +     riscv_iommu_writel(iommu, offset, val);                         \
> > +     return len;                                                     \
> > +}
> > +
> > +#define ATTR_WR_REG64(name, offset)                                  \
> > +     ssize_t reg_ ## name ## _store(struct device *dev,              \
> > +                     struct device_attribute *attr,                  \
> > +                     const char *buf, size_t len)                    \
> > +{                                                                    \
> > +     struct riscv_iommu_device *iommu = sysfs_dev_to_iommu(dev);     \
> > +     unsigned long long val;                                         \
> > +     int ret;                                                        \
> > +     ret = kstrtoull(buf, 0, &val);                                  \
> > +     if (ret)                                                        \
> > +             return ret;                                             \
> > +     riscv_iommu_writeq(iommu, offset, val);                         \
> > +     return len;                                                     \
> > +}
>
> So this allows users to change the registers through sysfs? How does
> it synchronize with the iommu driver?
>

The only writable registers are for debug interface and performance
monitoring counters, without any synchronization requirements between
user / driver.  In follow up patch series performance counters will be
also removed from sysfs, replaced by integration with perfmon
subsystem. The only remaining will be a debug access, providing user
access to address translation, in short it provides an interface to
query SPA based on provided IOVA/RID/PASID. There was a discussion in
RVI IOMMU TG forum if it's acceptable to expose such an interface to
the privileged user, and the conclusion was that it's very likely not
exposing more info than privileged users already are able to acquire
by looking at in-memory data structures.

Read-only registers are to provide debug access to track queue
head/tail pointers and interrupt states.

> Best regards,
> baolu

regards,
- Tomasz



More information about the linux-riscv mailing list