Exposing sensors (current, voltage, temperature) in a device

Hi,

We have developed a KMDF driver for a PCI Express device which has a number of sensors in it - specifically, voltages, currents and temperatures. We’ve got a proprietary API that exposes the sensors using ReadFile / DeviceIoControl etc. and that all works fine.

What we’d like to do now is expose the sensors in a way that integrates them into Windows so that they can be viewed or visualized using “standard utilities” (if there are any), and I’m looking for some guidance on the best way to do that.

What I’ve looked at so far is:

  1. Implement a user-mode driver for the “Sensor API”

https://docs.microsoft.com/en-gb/windows/desktop/SensorsAPI/portal

I have more or less discounted this as probably being overkill, overly complex for what we’re trying to do, and more aimed at mobile devices. However, I mention it in case I’m wrong to discount it.

  1. Expose the sensors by making our KMDF driver a WMI provider.

I guess this is the way to go. There are a few classes relating to sensors, and the ones that seem relevant are:

CIM_Sensor
NumericSensor
Sensor
Win32_CurrentProbe
Win32_VoltageProbe
Win32_TemperatureProbe

So I guess that the Win32_*Probe classes are what we should use. Actually, my understanding of the whole WMI thing is a bit shaky.

The docs say “Each driver should support any standard blocks defined for drivers of its type. Standard blocks provide WMI clients with consistent data for all devices of a given type, regardless of vendor.”

https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/supporting-standard-wmi-blocks

Does this mean that at WMI registration, our driver should create as many instances of (say) the Win32_*Probe classes as needed to expose our sensors?

My understanding is that if we do this (standard blocks only), we do not need to create our own MOF file - is that correct?

Am I correct in thinking that there is nothing built into Windows for displaying sensors that are exposed as instances of WMI classes?

These classes seem to have a whole bunch of properties that I don’t even understand, let alone can supply the proper values for. For example, Win32_TemperatureProbe has this:

SystemCreationClassName : The scoping System’s CreationClassName.

Am I going to have to read and absorb the CIM (Common Information Model) specification and dutifully provide good values for every property? Or can we cherry-pick and implement just the ones that we like the look of?

Apologies for the rambling, unfocussed questions, but I’m not really sure how to proceed. Thanks for any pointers!

Agreed. The sensor-class stuff isn’t what you’re looking for, unless you want to have Windows use it as input to control the fan speed or something.

Correct. I mean… what COULD there be, right? Your temperature sensor could be hooked-up to ANYthing. I don’t think there’s a built-in app that says “You wine cellar temperature is 60 degrees”… or “Your PCB etch bath temp is 105 degrees… have a nice day”

So, before I wave to you as you go down that long and painful path, I’ve just GOT to ask: Do you *really* think folks will care about using these interfaces to talk to your sensors?

I *get* that you can make the argument: Well, you can invoke WMI interfaces from just-about anywhere… C#, PowerShell, and what not. And you can’t do that with IOCTLs. Is that enough value for you to go through the effort?

I guess what I’m asking is… have your Product Management people done their due diligence and determined this is a good idea? Cuz my experience with WMI is that it’s not much fun.

Peter
OSR
@OSRDrivers

There is also a third, but it doesn’t really integrate with Windows:
create a library wrapping the DeviceIoControl and ReadFile calls by
stuffing that information into structure definitions you provide. This
is how it is typically done on Linux, and how device vendors do it
when targeting embedded developers who need to write host PC
applications.

You could consider providing first party (i.e. from you) bindings for
C#, Java, and Python, etc.

If you use WMI to grab Microsoft-implemented objects you will find
that the vast majority of properties aren’t populated (e.g. a
machine’s physical disks, should you wish to check). I take this to
mean that all values do not need to be valid.

This also makes me question the usefulness of WMI. If you know where
to look you can get the same information while skipping an extra step.
The extra information specified by the CIM would be what would make
WMI useful, but I never find it there.

I suppose in C# or PowerShell WMI is a bit easier to use than it is in
C++ which could be an argument for its use. Any native calls, like
SetupAPI, will be harder to do in C#, but after the initial work of
creating the PInvoke definitions (or using NuGet to fetch the PInvoke
library) you are done.

On Thu, Jul 5, 2018 at 10:45 AM, xxxxx@osr.com wrote:
> So, before I wave to you as you go down that long and painful path, I’ve just GOT to ask: Do you really think folks will care about using these interfaces to talk to your sensors?
>
> I get that you can make the argument: Well, you can invoke WMI interfaces from just-about anywhere… C#, PowerShell, and what not. And you can’t do that with IOCTLs. Is that enough value for you to go through the effort?
>
> I guess what I’m asking is… have your Product Management people done their due diligence and determined this is a good idea? Cuz my experience with WMI is that it’s not much fun.
>

Not to bike shed, but I’d like to second this - to me, WMI is a last
resort that I go to when information is only easily available in WMI.
Why is that information there in the first place, you ask? Because
Microsoft thought it should be in WMI, not because a meeting of third
party minds decided it should be in WMI.

Cheers,
R0b0t1

xxxxx@gmail.com wrote:

I suppose in C# or PowerShell WMI is a bit easier to use than it is in
C++ which could be an argument for its use.

You are underestimating this effect.  WMI is vastly, incredibly, HUGELY
easier to use in PowerShell and C#.  It’s almost fun.  I see people on
the C# forums using WMI to access information that I could do in a few
lines of C++, just because it’s easy.  If it were that easy in C++, we
would be seeing a lot more stuff accessed through WMI than we do today.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

@R0b0t1: We already have a proprietary API which uses ReadFile / DeviceIoControl, and it works fine.

@Peter & R0b0t1:

Here’s a bit more background on the device in question:

We have these PCI Express cards with one or more ginormous, expensive FPGAs on them, that can suck up a lot of electricity (like 100A @ 0.9V). These kinds of FPGAs can set you back several thousand dollars.

We’re in the embedded / datacenter / HPC market, and we get asked quite a lot about monitoring of power supplies and temperatures by customers.

The embedded people want to make sure they stay within power budget and that the FPGA isn’t cooking itself. In the datacenter market, they are accustomed to having IPMI and the like for health monitoring. Often they can’t easily get at the hardware once it is installed at some site, so they like to be able remotely monitor things. I think WMI and IPMI can interoperate somehow, but I don’t have an IPMI-enabled system to hand right now to figure out how that all hangs together.

During the development phase, some customers find it quite useful to measure actual currents so they can figure out if the latest iteration of their FPGA design increases or reduces power dissipation.

We’ve already got an equivalent Linux driver which registers itself with the hwmon subsystem. So, you just install the “standard” lm_sensors package, type “sensors *-pci-*”, and you get…

Adapter: PCI adapter
12V rail (edge conn.): +12.15 V
3.3V rail (edge conn.): +3.29 V
3.3V Aux rail (edge conn.): +3.25 V
2.5V (clock) power: +2.52 V
1.8V MGTVCCAux power: +1.80 V
1.2V DDR4 SDRAM power: +1.22 V
1.2V MGT AVTT: +1.20 V
0.9V MGT AVCC: +0.90 V
FPGA core power: +0.85 V
0.6V DDR4 SDRAM VTT: +0.61 V
uC internal temperature: +46.1?C
Board temperature at U89: +35.8?C
Board temperature at U90: +37.8?C
FPGA temperature: +44.1?C
12V current (edge conn.): +1.01 A
3.3V current (edge conn.): +0.84 A
1.8V MGTVCCAux current: +0.09 A
2.5V (digital) current : +0.49 A

Anyway, that’s the motivation - in our markets, people do care about this stuff. Although our little proprietary API might be is good enough for some people, some customers are sticklers for “open standards”. Management here thinks that it’s good to be able to tick the “supports open standards” box.

WMI looks unpleasant, which is probably why we haven’t bothered with it before now, but to me it looks like the nearest thing in Windows to Linux’s /sys filesystem.

By the way, what about kernel-mode performance counters? I came across an NVidia document that describes using perfmon.exe for visualizing performance counters in their driver, including temperature:

https://www.nvidia.co.uk/content/quadro_fx_product_literature/wp-06953-001-v02.pdf

I guess performance counters might be implemented on top of WMI somehow, but is this in fact a better way to go than plain old WMI?

On Thu, Jul 5, 2018 at 2:28 PM, xxxxx@alpha-data.com wrote:
> @R0b0t1: We already have a proprietary API which uses ReadFile / DeviceIoControl, and it works fine.
>
> @Peter & R0b0t1:
>
> Here’s a bit more background on the device in question:
>
> We have these PCI Express cards with one or more ginormous, expensive FPGAs on them, that can suck up a lot of electricity (like 100A @ 0.9V). These kinds of FPGAs can set you back several thousand dollars.
>
> We’re in the embedded / datacenter / HPC market, and we get asked quite a lot about monitoring of power supplies and temperatures by customers.
>
> The embedded people want to make sure they stay within power budget and that the FPGA isn’t cooking itself. In the datacenter market, they are accustomed to having IPMI and the like for health monitoring. Often they can’t easily get at the hardware once it is installed at some site, so they like to be able remotely monitor things. I think WMI and IPMI can interoperate somehow, but I don’t have an IPMI-enabled system to hand right now to figure out how that all hangs together.
>

I’m not sure it is right to say that IPMI can use WMI. It can probably
give you a gateway to the server network, which would let you connect
to the machine using remote WMI. Keep in mind the host would still
have to boot for this to work. Note also that every analysis of remote
WMI I have read has been fairly poor - it sounds like a hack (you
forward a static group of ports) and is hard to secure. In this sense
it should be viewed similar to some recently deprecated Microsoft
technology like NetDB, used for autoconfiguring networks. I suppose
administrators found it gave attackers too much information.

Of course this has no bearing on whether or not your customers want to use it.

> During the development phase, some customers find it quite useful to measure actual currents so they can figure out if the latest iteration of their FPGA design increases or reduces power dissipation.
>
> We’ve already got an equivalent Linux driver which registers itself with the hwmon subsystem. So, you just install the “standard” lm_sensors package, type “sensors -pci-”, and you get…
>
> Adapter: PCI adapter
> 12V rail (edge conn.): +12.15 V
> 3.3V rail (edge conn.): +3.29 V
> 3.3V Aux rail (edge conn.): +3.25 V
> 2.5V (clock) power: +2.52 V
> 1.8V MGTVCCAux power: +1.80 V
> 1.2V DDR4 SDRAM power: +1.22 V
> 1.2V MGT AVTT: +1.20 V
> 0.9V MGT AVCC: +0.90 V
> FPGA core power: +0.85 V
> 0.6V DDR4 SDRAM VTT: +0.61 V
> uC internal temperature: +46.1°C
> Board temperature at U89: +35.8°C
> Board temperature at U90: +37.8°C
> FPGA temperature: +44.1°C
> 12V current (edge conn.): +1.01 A
> 3.3V current (edge conn.): +0.84 A
> 1.8V MGTVCCAux current: +0.09 A
> 2.5V (digital) current : +0.49 A
>
> Anyway, that’s the motivation - in our markets, people do care about this stuff. Although our little proprietary API might be is good enough for some people, some customers are sticklers for “open standards”. Management here thinks that it’s good to be able to tick the “supports open standards” box.
>
> WMI looks unpleasant, which is probably why we haven’t bothered with it before now, but to me it looks like the nearest thing in Windows to Linux’s /sys filesystem.
>

I’m not sure you can consider WMI an open standard. A lot of the
available variables are not documented, and while you can use a wizard
to help you create WMI provider, the details of what are going on is
not self-evident.

I think you are right, however. It is very close to Linux’s /sys.
There are actually a bunch of namespaces on Windows under \ but I’ve
not yet found a good way to explore them in detail.

> By the way, what about kernel-mode performance counters? I came across an NVidia document that describes using perfmon.exe for visualizing performance counters in their driver, including temperature:
>
> https://www.nvidia.co.uk/content/quadro_fx_product_literature/wp-06953-001-v02.pdf
>
> I guess performance counters might be implemented on top of WMI somehow, but is this in fact a better way to go than plain old WMI?
>

It looks like performance counters are linked with WMI. See
https://docs.microsoft.com/en-us/windows/desktop/perfctrs/about-performance-counters
(a fairly new article). Hopefully you can get back to the list with
your ultimate choice.

Cheers,
R0b0t1

Alright, so I think I’ll have a go at exposing sensors as performance counters, since perfmon.exe looks like it will serve as a reasonable GUI. Then there’s the fact that you can log performance counters over time, which might be useful.

There is a “new” C++ WMI access framework which does make it easier. I think it’s called the MI framework. Still not as easy as access from a dynamic language like powershell.

Jan

-----Original Message-----
From: xxxxx@lists.osr.com On Behalf Of xxxxx@probo.com
Sent: Thursday, July 5, 2018 11:13 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Exposing sensors (current, voltage, temperature) in a device

xxxxx@gmail.com wrote:
> I suppose in C# or PowerShell WMI is a bit easier to use than it is in
> C++ which could be an argument for its use.

You are underestimating this effect. WMI is vastly, incredibly, HUGELY easier to use in PowerShell and C#. It’s almost fun. I see people on the C# forums using WMI to access information that I could do in a few lines of C++, just because it’s easy. If it were that easy in C++, we would be seeing a lot more stuff accessed through WMI than we do today.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>

It’s interesting to hear you say WMI has not been much fun. I’ve had the opposite experience, and frequently make WMI interfaces for drivers, even if it’s just for a test interface during development.

My current tendency is to make a single WMI interface class, with a class name like Company_Product_Interface, that often has minimal data fields like a driver version, and has a bunch of WMI methods to query/set stuff. The reason for this style is it’s easy to make variable size in or out parameters for a method, and much harder for a class. KMDF also has terrible support (like none) for dynamic WMI instances, but it’s easy to have a method that returns a variable size array of WMI objects of a custom WMI class. This kind of interface is not expected to be compatible with any other WMI interface, so is not directly usable by standard tools like perfmon. It’s really optimized for manual use or from a powershell script or C++/C# code.

About two years ago I was doing a high speed fabric driver, and the drivers exposed a huge amount of low level operation/performance data through the WMI interface, things like queue ring pointers, interrupt rates, fragments/sec. I then had a powershell script that created a window with a web browser in it. The powershell code had a timer, and once a second would poll the device performance data through the WMI method interfaces, and write some dynamic html into the web browser, which then did pretty rendering. This was an enormously useful tool for debugging and performance optimization, as when running a test load you could easily see the summary performance metrics that mattered. As a debugging, the early silicon had a errata that sometimes caused a ring to get stuck, and it was instantly apparent on the web page updating every second when you hit this condition. I’ve used this exact kind of thing in the past for customer support debugging, and had a script that could instantly determine if the product was likely operating correctly, and if not what subsystem had a problem. This support WMI interface could dump all the device registers in a format that was useful for technical support engineers.

About 5 years ago, I worked on a communication protocol driver, and it used a WMI interface for exercising all the little corners of the protocol. There was a powershell script that made WMI calls to initiate connections, set parameters, and do data transfers. The WMI interface was actually to a test driver that called the protocol driver, and was written concurrently with the protocol driver. I used the test driver during development to exercise all kinds of paths, and inject error conditions, and collect operational data. The test driver was designed like this so it could test an interface API, which was then used by other components in the product. There was going to be multiple implementations of the protocol driver, one in pure software using kernel sockets, and one that used an interface much more tied to the hardware.

My biggest complaint about WMI is the WDK driver creation wizard does not automatically generate WMI code. I find I almost always have a WMI interface in drivers, and have to manually add essentially boilerplate code every time I do a new driver. Some of the docs on WMI are a bit lacking too

Some things I really like about WMI include:

  1. The data has rich metadata, so calling from a dynamic script language is really easy
  2. Performance is “good enough” for lots of uses, in the range of 1000 method calls/sec
  3. WMI data is accessible remotely, so my desktop can read WMI data from any remote machine
  4. Once you add the initialization boilerplate code, adding a new method is easy
  5. There is a single consistent access method for kernel or user WMI providers
  6. Linux folks can understand when you tell them WMI is like a /sys interface

Jan

-----Original Message-----
From: xxxxx@lists.osr.com On Behalf Of xxxxx@osr.com
Sent: Thursday, July 5, 2018 8:46 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Exposing sensors (current, voltage, temperature) in a device

Agreed. The sensor-class stuff isn’t what you’re looking for, unless you want to have Windows use it as input to control the fan speed or something.



Correct. I mean… what COULD there be, right? Your temperature sensor could be hooked-up to ANYthing. I don’t think there’s a built-in app that says “You wine cellar temperature is 60 degrees”… or “Your PCB etch bath temp is 105 degrees… have a nice day”

So, before I wave to you as you go down that long and painful path, I’ve just GOT to ask: Do you really think folks will care about using these interfaces to talk to your sensors?

I get that you can make the argument: Well, you can invoke WMI interfaces from just-about anywhere… C#, PowerShell, and what not. And you can’t do that with IOCTLs. Is that enough value for you to go through the effort?

I guess what I’m asking is… have your Product Management people done their due diligence and determined this is a good idea? Cuz my experience with WMI is that it’s not much fun.

Peter
OSR
@OSRDrivers


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>