Ah ok, good to know.

Thanks anyway.


2017-03-27 14:57 GMT+02:00, Mark Kettenis <[email protected]>:
>> From: Simon Mages <[email protected]>
>> Date: Mon, 27 Mar 2017 13:57:54 +0200
>>
>> Hi,
>>
>> right now i use the following diff to poke around in the PCIe config
>> space. This diff enables
>> pcidump to read and write to a register. So far i used this mainly to
>> play with the Advanced
>> Error Reporting Capability some devices have.
>>
>> $ pcidump 4:0:0:104
>>  4:0:0: Broadcom BCM5754
>>         0x0104: 0x00100000
>> This bit indicates an "Unsupported Request Error", the register
>> queried here is the
>> "Uncorrectable Error Status Register".
>>
>> # pcidump 4:0:0:104:0x00100000
>>  4:0:0: Broadcom BCM5754
>>         0x0104: 0x00000000
>> pcidump shows the new value of the register after writing. By writing
>> a 1 to a status bit it
>> gets reset.
>>
>> I implemented a check for the current securelevel because writing to
>> /dev/pci is only possible
>> for a securelevel smaller than 1.
>>
>> I think this functionality can come in handy for people
>> writing/modifying device drivers.
>
> Sorry, but no.  This is not going to happen.  The kernel interface to
> write to pci config space is only there to support X.  And even that
> support is likely to disappear at some point.
>
>> Index: pcidump.8
>> ===================================================================
>> --- pcidump.8        16 Jul 2013 11:13:34 -0000      1.12
>> +++ pcidump.8        27 Mar 2017 11:27:35 -0000
>> @@ -26,7 +26,7 @@
>>  .Op Fl x | xx | xxx
>>  .Op Fl d Ar pcidev
>>  .Sm off
>> -.Op Ar bus : dev : func
>> +.Op Ar bus : dev : func [ : reg [ : val ] ]
>>  .Sm on
>>  .Nm pcidump
>>  .Fl r Ar file
>> @@ -69,16 +69,29 @@ Shows a hexadecimal dump of the full PCI
>>  Shows a hexadecimal dump of the PCIe extended config space.
>>  .It Xo
>>  .Sm off
>> -.Ar bus : dev : func
>> +.Ar bus : dev : func [ : reg [ : val ] ]
>>  .Sm on
>>  .Xc
>>  Show information about the PCI device specified by the tuple given on
>> -the command line.
>> +the command line. If
>> +.Pa reg
>> +is used, the value of this register in the configuration space of
>> +.Pa func
>> +gets printed. If
>> +.Pa val
>> +is used, the register specified by
>> +.Pa reg
>> +will be loaded with the value specified by
>> +.Pa val .
>>  If the
>>  .Fl d
>>  option is not given,
>>  .Pa /dev/pci
>>  is used.
>> +.It Xo
>> +.Xc
>> +The configuration space can only be written in a securelevel(7) lower
>> +than 1.
>>  .El
>>  .Sh FILES
>>  .Bl -tag -width /dev/pci* -compact
>> @@ -86,7 +99,8 @@ is used.
>>  Device files for accessing PCI domains.
>>  .El
>>  .Sh SEE ALSO
>> -.Xr pci 4
>> +.Xr pci 4 ,
>> +.Xr securelevel 7
>>  .Sh HISTORY
>>  The
>>  .Nm
>> Index: pcidump.c
>> ===================================================================
>> --- pcidump.c        25 Mar 2017 07:33:46 -0000      1.43
>> +++ pcidump.c        27 Mar 2017 11:24:10 -0000
>> @@ -19,6 +19,8 @@
>>  #include <sys/types.h>
>>  #include <sys/ioctl.h>
>>  #include <sys/pciio.h>
>> +#include <sys/param.h>
>> +#include <sys/sysctl.h>
>>
>>  #include <stdio.h>  /* need NULL for <dev/pci/*.h> */
>>
>> @@ -37,19 +39,27 @@
>>
>>  #define PCIDEV      "/dev/pci"
>>
>> +#define PCI_CONFIG_SPACE_BEGIN      0x0
>> +#define PCIE_CONFIG_SPACE_END       (PCIE_CONFIG_SPACE_SIZE - 1)
>> +#define PCI_CONFIG_ALIGNMENT        0x4
>> +#define REG_ALIGNMENT_OK(x) ((x) % PCI_CONFIG_ALIGNMENT ? 0 : 1)
>> +
>>  #ifndef nitems
>>  #define nitems(_a)  (sizeof((_a)) / sizeof((_a)[0]))
>>  #endif
>>
>>  __dead void usage(void);
>> +int get_securelevel(void);
>>  void scanpcidomain(void);
>> -int probe(int, int, int);
>> +int probe(int, int, int, int, int);
>> +void chreg(int, int, int, int, int);
>>  void dump(int, int, int);
>>  void hexdump(int, int, int, int);
>> -const char *str2busdevfunc(const char *, int *, int *, int *);
>> +const char *str2busdevfunc(const char *, int *, int *, int *, int *, int
>> *);
>>  int pci_nfuncs(int, int);
>>  int pci_read(int, int, int, u_int32_t, u_int32_t *);
>>  int pci_readmask(int, int, int, u_int32_t, u_int32_t *);
>> +int pci_write(int, int, int, u_int32_t, u_int32_t);
>>  void dump_caplist(int, int, int, u_int8_t);
>>  void dump_pci_powerstate(int, int, int, uint8_t);
>>  void dump_pcie_linkspeed(int, int, int, uint8_t);
>> @@ -67,7 +77,8 @@ usage(void)
>>      extern char *__progname;
>>
>>      fprintf(stderr,
>> -        "usage: %s [-v] [-x | -xx | -xxx] [-d pcidev] [bus:dev:func]\n"
>> +        "usage: %s [-v] [-x | -xx | -xxx] [-d pcidev]"
>> +        " [bus:dev:func[:reg[:val]]]\n"
>>          "       %s -r file [-d pcidev] bus:dev:func\n",
>>          __progname, __progname);
>>      exit(1);
>> @@ -139,7 +150,7 @@ int
>>  main(int argc, char *argv[])
>>  {
>>      int nfuncs;
>> -    int bus, dev, func;
>> +    int bus, dev, func, reg = -1, val = -1;
>>      char pcidev[PATH_MAX] = PCIDEV;
>>      char *romfile = NULL;
>>      const char *errstr;
>> @@ -186,7 +197,10 @@ main(int argc, char *argv[])
>>              dumpall = 0;
>>
>>      if (dumpall == 0) {
>> -            pcifd = open(pcidev, O_RDONLY, 0777);
>> +            if (get_securelevel() < 1)
>> +                    pcifd = open(pcidev, O_RDWR, 0777);
>> +            else
>> +                    pcifd = open(pcidev, O_RDONLY, 0777);
>>              if (pcifd == -1)
>>                      err(1, "%s", pcidev);
>>      } else {
>> @@ -207,7 +221,7 @@ main(int argc, char *argv[])
>>      }
>>
>>      if (argc == 1) {
>> -            errstr = str2busdevfunc(argv[0], &bus, &dev, &func);
>> +            errstr = str2busdevfunc(argv[0], &bus, &dev, &func, &reg, &val);
>>              if (errstr != NULL)
>>                      errx(1, "\"%s\": %s", argv[0], errstr);
>>
>> @@ -217,7 +231,7 @@ main(int argc, char *argv[])
>>              else if (romfile)
>>                      error = dump_rom(bus, dev, func);
>>              else
>> -                    error = probe(bus, dev, func);
>> +                    error = probe(bus, dev, func, reg, val);
>>
>>              if (error != 0)
>>                      errc(1, error, "\"%s\"", argv[0]);
>> @@ -229,6 +243,25 @@ main(int argc, char *argv[])
>>      return (0);
>>  }
>>
>> +int
>> +get_securelevel(void)
>> +{
>> +    int name[2], seclvl;
>> +    size_t len;
>> +
>> +    name[0] = CTL_KERN;
>> +    name[1] = KERN_SECURELVL;
>> +
>> +    len = sizeof(seclvl);
>> +
>> +    if (sysctl(name, 2, &seclvl, &len, NULL, 0) == -1) {
>> +            errx(1, "sysctl securelevel: %s", strerror(errno));
>> +            return (-1);
>> +    }
>> +
>> +    return seclvl;
>> +}
>> +
>>  void
>>  scanpcidomain(void)
>>  {
>> @@ -239,17 +272,18 @@ scanpcidomain(void)
>>              for (dev = 0; dev < 32; dev++) {
>>                      nfuncs = pci_nfuncs(bus, dev);
>>                      for (func = 0; func < nfuncs; func++) {
>> -                            probe(bus, dev, func);
>> +                            probe(bus, dev, func, -1, -1);
>>                      }
>>              }
>>      }
>>  }
>>
>>  const char *
>> -str2busdevfunc(const char *string, int *bus, int *dev, int *func)
>> +str2busdevfunc(const char *string, int *bus, int *dev, int *func, int
>> *reg,
>> +    int *val)
>>  {
>>      const char *errstr;
>> -    char b[80], *d, *f;
>> +    char b[80], *d, *f, *r, *v;
>>
>>      strlcpy(b, string, sizeof(b));
>>
>> @@ -263,6 +297,15 @@ str2busdevfunc(const char *string, int *
>>              return("function not specified");
>>      *f++ = '\0';
>>
>> +    r = strchr(f, ':');
>> +    if (r != NULL) {
>> +            *r++ = '\0';
>> +
>> +            v = strchr(r, ':');
>> +            if (v != NULL)
>> +                    *v++ = '\0';
>> +    }
>> +
>>      *bus = strtonum(b, 0, 255, &errstr);
>>      if (errstr != NULL)
>>              return (errstr);
>> @@ -273,11 +316,24 @@ str2busdevfunc(const char *string, int *
>>      if (errstr != NULL)
>>              return (errstr);
>>
>> +    if (r != NULL) {
>> +            /* a non-PCIe function will return (u_int)-1 on a
>> +             * read above 0xfff */
>> +            if (sscanf(r, "%x", reg) == EOF
>> +                || *reg < PCI_CONFIG_SPACE_BEGIN
>> +                || *reg > PCIE_CONFIG_SPACE_END
>> +                || !REG_ALIGNMENT_OK(*reg))
>> +                    return("invalid register");
>> +
>> +            if ((v != NULL) && (sscanf(v, "%x", val) == EOF))
>> +                    return("invalid value");
>> +    }
>> +
>>      return (NULL);
>>  }
>>
>>  int
>> -probe(int bus, int dev, int func)
>> +probe(int bus, int dev, int func, int reg, int val)
>>  {
>>      u_int32_t id_reg;
>>      const struct pci_known_vendor *pkv;
>> @@ -311,6 +367,8 @@ probe(int bus, int dev, int func)
>>          (vendor == NULL) ? "unknown" : vendor,
>>          (product == NULL) ? "unknown" : product);
>>
>> +    if (reg > -1)
>> +            chreg(bus, dev, func, reg, val);
>>      if (verbose)
>>              dump(bus, dev, func);
>>      if (hex > 0)
>> @@ -320,6 +378,25 @@ probe(int bus, int dev, int func)
>>  }
>>
>>  void
>> +chreg(int bus, int dev, int func, int reg, int val)
>> +{
>> +    u_int32_t regval;
>> +    int tmp;
>> +
>> +    if (val > -1) {
>> +            if ((tmp = pci_write(bus, dev, func, reg, val)) != 0) {
>> +                    err(1, "pci_write");
>> +                    return;
>> +            }
>> +    }
>> +
>> +    if (pci_read(bus, dev, func, reg, &regval) != 0)
>> +            return;
>> +
>> +    printf("\t0x%04x: 0x%08x\n", reg, regval);
>> +}
>> +
>> +void
>>  dump_pci_powerstate(int bus, int dev, int func, uint8_t ptr)
>>  {
>>      u_int32_t pmcsr;
>> @@ -800,6 +877,27 @@ pci_readmask(int bus, int dev, int func,
>>              return (rv);
>>
>>      *val = io.pi_data;
>> +
>> +    return (0);
>> +}
>> +
>> +int
>> +pci_write(int bus, int dev, int func, u_int32_t reg, u_int32_t val)
>> +{
>> +    struct pci_io io;
>> +    int rv;
>> +
>> +    bzero(&io, sizeof(io));
>> +    io.pi_sel.pc_bus = bus;
>> +    io.pi_sel.pc_dev = dev;
>> +    io.pi_sel.pc_func = func;
>> +    io.pi_reg = reg;
>> +    io.pi_width = 4;
>> +    io.pi_data = val;
>> +
>> +    rv = ioctl(pcifd, PCIOCWRITE, &io);
>> +    if (rv != 0)
>> +            return (rv);
>>
>>      return (0);
>>  }
>>
>>
>

Reply via email to