lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <YhttzgDtGpcTniyw@hatter.bewilderbeest.net>
Date:   Sun, 27 Feb 2022 04:25:50 -0800
From:   Zev Weiss <zev@...ilderbeest.net>
To:     Guenter Roeck <linux@...ck-us.net>
Cc:     linux-hwmon@...r.kernel.org, Jean Delvare <jdelvare@...e.com>,
        openbmc@...ts.ozlabs.org, linux-kernel@...r.kernel.org,
        Renze Nicolai <renze@...lus.nl>,
        Rob Herring <robh+dt@...nel.org>, devicetree@...r.kernel.org,
        Denis Pauk <pauk.denis@...il.com>
Subject: Re: [PATCH 0/5] hwmon: (nct6775) Add i2c support

[Adding Denis re: wmi discussion below...]

On Sat, Feb 26, 2022 at 03:54:42PM PST, Guenter Roeck wrote:
>On 2/26/22 05:30, Zev Weiss wrote:
>>Hello,
>>
>>This patch series augments the existing nct6775 driver with support
>>for the hardware's i2c interface.
>>
>>Thus far the nct6775 driver has only supported the LPC interface,
>>which is the main interface by which the Super-I/O chip is typically
>>connected to the host (x86) processor.
>>
>>However, these chips also provide an i2c interface, which can provide
>>a way for a BMC to also monitor sensor readings from them.  On some
>>systems (such as the ASRock Rack ROMED8HM3 and X570-D4U) this may be
>>the only way for the BMC to monitor host CPU temperatures (e.g. to
>>indirectly access a TSI interface); this functionality is thus an
>>important component of enabling OpenBMC to support such systems.
>>
>>In such an arrangement the Super-I/O chip is simultaneously controlled
>>by two independent processors (the host and the BMC) which typically
>>do not coordinate their accesses with each other.  In order to avoid
>>conflicts between the two, the i2c driver avoids all writes to the
>>device, since the BMC's needs with the hardware are merely that it be
>>able to retrieve sensor readings.  This allows the host processor to
>>remain ultimately in control of the chip and unaware of the BMC's use
>>of it at all.
>>
>>The sole exception to the "no writes" rule for the i2c driver is for
>>the bank-select register -- while I haven't been able to find any
>>explicit statement in the Nuvoton datasheets guaranteeing this, all
>>experiments I've done have indicated that, as one might hope, the i2c
>>interface has its own bank-select register independent of the one used
>>by the LPC interface.
>>
>
>That will a more detailed confirmation. Please explain in detail
>the experiments you have done.
>
>Other chips (specifically those served by the it87 driver) have the
>same problem, and there it was never really solved. That resulted
>in random crashes. I don't want to end up in the same situation.
>

On an ASRock Rack ROMED8HM3, I used the following program to manually 
peek and poke device registers from the host:

host# cat port.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/io.h>

int main(int argc, char** argv)
{
	unsigned long addr, val;

	if (iopl(3)) {
		perror("iopl");
		exit(1);
	}

	if (argc == 3 && !strcmp(argv[1], "r")) {
		addr = strtoul(argv[2], NULL, 0);
		printf("%03lx: %02x\n", addr, inb(addr));
	} else if (argc == 4 && !strcmp(argv[1], "w")) {
		addr = strtoul(argv[2], NULL, 0);
		val = strtoul(argv[3], NULL, 0);
		printf("%03lx <- %02lx\n", addr, val);
		outb(val, addr);
	} else {
		fprintf(stderr, "Usage: %s [rw] ADDR [VALUE]\n", argv[0]);
		exit(1);
	}

	return 0;
}
host# cc -o port port.c

At the same time, I used i2cget & i2cset to do the same from the BMC 
(the nct6779 is at address 0x2d on bus 1).

Interleaving some shell transcripts chronologically (no drivers bound on 
either processor):

   host# ./port w 0x295 0x4e && ./port r 0x296
   295 <- 4e
   296: 08

   bmc# i2cget -y 1 0x2d 0x4e
   0x02
   bmc# i2cset -y 1 0x2d 0x4e 0x01
   bmc# i2cget -y 1 0x2d 0x4e
   0x01

   host# ./port w 0x295 0x4e && ./port r 0x296
   295 <- 4e
   296: 08

So, starting from an initial state where the two sides were reporting 
different values for the bank select register, a write to the bank 
select register via the BMC's i2c interface is seen by a subsequent read 
over that same interface, but the host still sees the same value it saw 
initially.

Reversing the roles (host writing the bank-select register), the BMC is 
likewise unaffected:

   bmc# i2cget -y 1 0x2d 0x4e
   0x01

   host# ./port w 0x295 0x4e && ./port r 0x296
   295 <- 4e
   296: 08
   host# ./port w 0x295 0x4e && ./port w 0x296 0x06
   295 <- 4e
   296 <- 06
   host# ./port w 0x295 0x4e && ./port r 0x296
   295 <- 4e
   296: 06

   bmc# i2cget -y 1 0x2d 0x4e
   0x01

In contrast, looking at a different read/write register (the config 
register at 0x40 in bank 0, for example), writes from each side are seen 
by the other:

   host# ./port w 0x295 0x4e && ./port w 0x296 0x00
   295 <- 4e
   296 <- 00
   host# ./port w 0x295 0x40 && ./port r 0x296
   295 <- 40
   296: 03

   bmc# i2cset -y 1 0x2d 0x4e 0x00
   bmc# i2cget -y 1 0x2d 0x40
   0x03
   bmc# i2cset -y 1 0x2d 0x40 0x01
   bmc# i2cget -y 1 0x2d 0x40
   0x01

   host# ./port w 0x295 0x40 && ./port r 0x296
   295 <- 40
   296: 01
   host# ./port w 0x295 0x40 && ./port w 0x296 0x03
   295 <- 40
   296 <- 03
   host# ./port w 0x295 0x40 && ./port r 0x296
   295 <- 40
   296: 03

   bmc# i2cget -y 1 0x2d 0x40
   0x03

To be cautious we could perhaps trim down the list of supported chips in 
the i2c driver to include only the models that are known to pass tests 
like the above; I can certainly make that change if that would be 
preferred.

>>In terms of code structure, the approach taken in this series is to
>>split the LPC-specific parts of the driver out into a separate module
>>(called nct6775-platform), leaving the interface-independent parts in
>>a generic driver (called nct6775-core).  The nct6775-i2c driver is
>>then added as an additional consumer of the nct6775-core module's
>>functionality.
>>
>
>How about wmi ? Shouldn't that be separated as well ?
>

I admittedly don't know much about wmi, but from what I could see in the 
code it looked to me like it essentially just acts as an alternate 
software/firmware path to the same underlying LPC interface, so I 
figured it would make sense to leave it integrated with the rest of the 
platform driver as it is currently.  If there's a particular benefit to 
be gained from splitting it out as well I can look into doing so, but 
from my current understanding it seems like it would lead to either:

  - duplication between the wmi and bare inb/outb versions of the 
    platform driver, or

  - to eliminate the duplication, a third (intermediate) module 
    containing the code that was common to the two of them, leaving the 
    two platform driver modules as little else than the bare register I/O 
    routines (superio_[wmi_]inb, nct6775_[wmi_]read_value, etc.), i.e.  
    the differences that are already handled via the indirection of the 
    function pointers Denis added recently.

I suppose the hypothetical intermediate module in the second scenario 
above could also be integrated back into nct6775-core, though that part 
of it would then be needless dead weight for the typically more 
resource-constrained systems (e.g. BMCs) that are only going to use the 
i2c driver.

Anyway, none of the above possibilities seemed terribly appealing to me, 
but if there's something I've misunderstood or factors I haven't taken 
into account please let me know.


Thanks,
Zev

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ