__try __except on high irql

Hello!

I use function like this to get msr value:

__int64 support::query_msr(NTSTATUS& stat, int msr_index)
{
stat = STATUS_SUCCESS;

__int64 msr(0);

__try
{
msr = __readmsr(msr_index);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
stat = GetExceptionCode();
}

return msr;
}

Is it safe to use __try__except block at high irql ?
I checked this in win10 x64 at ipi level with invalid msr index 0xffffffff
and it works (I get error as expected).
So in this test it works, but is it safe in general ?

Well, all IRQL- related restrictions are based upon interactions with the system dispatcher.
Although some may think of it as of something absolute and ultimate that has to be treated in religious-like fashion, in actuality, it just indicates which kind of interaction with the system dispatcher may be problematic at the particular moment.

Structured exception handling per se is all about setting up the stack frame in a particular way - it does not seem to involve interactions with the system dispatcher in any possible way. Therefore, I don’t see any reason why it should pose any problem at any IRQL. Certainly, there may be some IRQL- related restrictions when the system-provided exception handler (i.e. pointed to by IDT) has to interact with the system dispatcher before calling your custom one . For example, if you touch an invalid address at elevated IRQL you are going to bugcheck regardless of your exception handler, because the system-provided page fault handler may have to put the offending thread to sleep before your custom exception handler gets a chance to run. However, this does not seem to apply to your case, does it.

This is just my opinion that is based upon the logical analysis and seems to be backed up by your practical experiment. However, I don’t exclude the possibility of hearing some other opinions from the usual suspects who would require the official MSDN backup and warn you of some potential “dangers”…

Anton Bassov

Thank you, Anton!

I think this should work too. But I guess I am one of the people who would
prefer official MSDN backup :slight_smile:

On Wed, Apr 18, 2018 at 7:03 PM, xxxxx@hotmail.com <
xxxxx@lists.osr.com> wrote:

Well, all IRQL- related restrictions are based upon interactions with the
system dispatcher.
Although some may think of it as of something absolute and ultimate that
has to be treated in religious-like fashion, in actuality, it just
indicates which kind of interaction with the system dispatcher may be
problematic at the particular moment.

Structured exception handling per se is all about setting up the stack
frame in a particular way - it does not seem to involve interactions with
the system dispatcher in any possible way. Therefore, I don’t see any
reason why it should pose any problem at any IRQL. Certainly, there may be
some IRQL- related restrictions when the system-provided exception handler
(i.e. pointed to by IDT) has to interact with the system dispatcher before
calling your custom one . For example, if you touch an invalid address at
elevated IRQL you are going to bugcheck regardless of your exception
handler, because the system-provided page fault handler may have to put the
offending thread to sleep before your custom exception handler gets a
chance to run. However, this does not seem to apply to your case, does it.

This is just my opinion that is based upon the logical analysis and seems
to be backed up by your practical experiment. However, I don’t exclude the
possibility of hearing some other opinions from the usual suspects who
would require the official MSDN backup and warn you of some potential
“dangers”…

Anton Bassov


NTDEV is sponsored by OSR

Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> 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://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:>

xxxxx@gmail.com wrote:

I use function like this to get msr value:

__int64 support::query_msr(NTSTATUS& stat, int msr_index)

I have a couple of philosophical points about this, take it or leave it.

It seems to me that it would be much more appropriate to have the
signature be:
    NTSTATUS support::query_msr( __int64 & value, int msr_index );
or even
    NTSTATUS support::query_msr( int msr_index, __int64 & value );

Every kernel API that can produce a status returns it as the return of
the function.  That is how people expect to use such functions.  This is
supportable from an engineering sense; you need to ask “did the function
succeed?” before you go to use the result of the function.

But even more, why do this error checking in the first place?  Based on
the kernel philosophy that “kernel code is trusted code”, you should be
able to rely on your callers not to do stupid things in the first
place.   __try/__except incurs overhead.  One could argue that it would
be better to let the system crash when a kernel caller misuses an
internal API.  If you’re accepting MSR addresses from user mode, then
yes, you need to validate them.


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

Thank you Tim!

I tend to return result of operation in my internal functions and not
status. This way it is easy to initialise auto pointers. For example:

do
{
auto_pointer obj(create_my_object(status));
if(!NT_SUCCESS(stat))
{
break;
}
}while(false);

Of course create_my_object returns null pointer if status is not success;
Plus reference/pointer to status is the only way to return status from
constructor in absence of c++ exceptions.
So this way my code looks more uniformly.
In case of pure C I would indeed return status and not result though. So in
some way I actually agree with you.

I need support of some hardware features from cpu.
I can check this support in two ways:
1) Maintain list of supported cpu models (and update this list all the time)
2) Just query msr I need and let processor to throw general protection
exception (and catch it of course) in case this feature is not supported.

I like second way much more.

On Wed, Apr 18, 2018 at 8:13 PM, xxxxx@probo.com wrote:

> xxxxx@gmail.com wrote:
> >
> > I use function like this to get msr value:
> >
> > __int64 support::query_msr(NTSTATUS& stat, int msr_index)
>
> I have a couple of philosophical points about this, take it or leave it.
>
> It seems to me that it would be much more appropriate to have the
> signature be:
> NTSTATUS support::query_msr(__int64 & value, int msr_index );
> or even
> NTSTATUS support::query_msr( int msr_index, __int64 & value );
>
> Every kernel API that can produce a status returns it as the return of
> the function. That is how people expect to use such functions. This is
> supportable from an engineering sense; you need to ask “did the function
> succeed?” before you go to use the result of the function.
>
> But even more, why do this error checking in the first place? Based on
> the kernel philosophy that “kernel code is trusted code”, you should be
> able to rely on your callers not to do stupid things in the first
> place.__try/__except incurs overhead. One could argue that it would
> be better to let the system crash when a kernel caller misuses an
> internal API. If you’re accepting MSR addresses from user mode, then
> yes, you need to validate them.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> 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://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:>

How about probing the needed MSRs first in context where SEH is safe (ex. in your DriverEntry) and avoid touching bad MSRs later?

– pa

Thank you Pavel !

Indeed I can do that and it will work since all cores are identical in
current cpus. However intel itself recommends check each core capabilities
independently. I guess in theory intel can create processor with
non-identical cores.

On Thu, 19 Apr 2018 at 00:27, xxxxx@fastmail.fm
wrote:

> How about probing the needed MSRs first in context where SEH is safe (ex.
> in your DriverEntry) and avoid touching bad MSRs later?
>
> – pa
>
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: <
> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>
> 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://www.osronline.com/page.cfm?name=ListServer&gt;
></http:>

I suppose a related question is: if the OS is running as a VM, and that VM is live migrated to a different host, is it possible the available MSR’s will suddenly be different. I know live VMs can only be migrated to “similar” hosts, like don’t believe you can migrate a VM on a Intel cpu to an AMD cpu without a reboot. I don’t believe the host CPUs have to be identical model numbers. They are called Model Specific Registers for a reason.

Jan

From: xxxxx@lists.osr.com On Behalf Of xxxxx@gmail.com
Sent: Wednesday, April 18, 2018 2:41 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] try except on high irql

Thank you Pavel !

Indeed I can do that and it will work since all cores are identical in current cpus. However intel itself recommends check each core capabilities independently. I guess in theory intel can create processor with non-identical cores.

On Thu, 19 Apr 2018 at 00:27, xxxxx@fastmail.fmmailto:xxxxx > wrote:
How about probing the needed MSRs first in context where SEH is safe (ex. in your DriverEntry) and avoid touching bad MSRs later?

– pa


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:
— NTDEV is sponsored by OSR Visit the list online at: MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers! Details at To unsubscribe, visit the List Server section of OSR Online at</http:></http:></http:></mailto:xxxxx>

Life used to be simple, didn’t it: Wanna know how many CPUs were in the system or how much memory there is? Check in DriverEntry and size your data structures appropriately. Wanna know what model system you’re running on? Check in DriverEntry and setup some static data.

Live migration, hot add of processors and memory… It’s so much more complex now. And we HAVE to keep this in mind.

Peter
OSR
@OSRDrivers

> However intel itself recommends check each core capabilities independently.

I guess in theory intel can create processor with non-identical cores.

Well,concerning “non-identical cores”, the suggestion is, IMHO, although not infeasible in theory,
still highly unlikely, at least in practical terms. I would not be too much bothered about it.

What I would be bothered about (at least on a server-grade system with support for hotplug ) is that a CPU gets dynamically added/changed while the system is still running. IIRC, the same mobo may support a relatively wide array of CPU versions within a given family, or, probably even different CPU families . Although the differences between CPUs are unlikely to be really dramatic, they may still be sufficient for practically considering the scenario of certain model-specific features being different across the different CPUs on the same system andd/or dynamically changing at a runtime.

Anton Bassov

There’s theory and reality. In reality, in the cases I’m familiar with, the system is most happy when the sockets on multi-socket main boards all contain not only the same MODEL, but the same STEPPING of that model.

That doesn’t mean that I would design to that as a limitation. I think probably the “best practice” would be to assume that each core could be different, and could dynamically change. You handle those changes asynchronously, of course. There’s a Processor Change Callback just for this purpose.

Peter
OSR
@OSRDrivers

Processor Change callback? What it is? The documentation mentions only Processor Add callback

https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-a-system-defined-callback-object

– pa

> Processor Change callback? What it is?

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-keregisterprocessorchangecallback

Anton Bassov

Thank you, Mr. Bassov. Exactly correct: KeRegisterProcessorChangeCallback

Peter
OSR
@OSRDrivers

I respectfully apologize, but even KeRegisterProcessorChangeCallback documentation tells only about adding of a new CPU, not about change of the CPU type or anything else.

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-keregisterprocessorchangecallback

Should we file a docum bug to revise this page?

Regards,

    • pa

> even KeRegisterProcessorChangeCallback documentation tells only about adding

of a new CPU, not about change of the CPU type or anything else.

Just try to think about the process of changing the CPU carefully. Unless we imagine the CPU that can dynamically reconfigure its own features (which, IMHO, would invariably involve resetting itself as far as its client software is concerned anyway - it just does not seem to be the kind of thing that is feasible at a runtime), it must involve at least 2 stages

  1. Unplugging some existing CPU

  2. Plugging in a new one instead

Once your callback is invoked every time part (2) takes place, it allows you to track both
adding the new CPUs (i.e. increasing the total number of CPUs in the system) AND changing
(i.e.going through remove - add sequence) them. Does not really seem to be a rocket science, does it…

Anton Bassov

What Mr. Bassov said. Gad, I can hardly believe I typed that. Once in a while, huh?

It hinges on the meaning of the phrase “processor change” – The processor state itself is “changed” (that is, a processor is removed and/or added). This isn’t a callback to indicate that the existing processor has somehow “morphed itself” (changed its characteristics).

Peter
OSR
@OSRDrivers

> Gad, I can hardly believe I typed that

Me too… because, there’s no point 1. No case for unplug or removal. The docum tells only about adding CPUs.

Maybe KeRegisterProcessorChangeCallback was intended for more, but as described, it is just a moral equivalent of \Callback\ProcessorAdd, with an extra “observer pattern” bit.

– pa

> Unless we imagine…it just does not seem to be the kind of thing that is feasible at a runtime

This kind of thinking has caused more problems over the years in the windows subsystem than you can imagine. Whenever someones limited imagination is the basis of a decision on what might be possible, the future always proves it wrong sooner or later. This bad line of thinking started in Windows 95 when people made decisions on what could or couldn’t be PnP based on their limited imaginations. Over the years everything became PnP creating headaches because windows was hard wired such that many types of hardware could never be PnP. Again and again we see this happen. Please take what you wrote in that post, file it away somewhere with a reminder to look at it 15 years from now and have a good laugh.

API’s should never be limited to one’s imagination of what is possible! There should be no limits.

Well, it s hard to say what kind of “thinking” you are speaking about, taking into consideration that you take certain parts of someone’s statement while discarding the others, effectively stripping the original statement of its actual meaning and assigning a totally different one to it…

Whenever someones limited imagination is the basis of a decision on what might
be possible, the future always proves it wrong sooner or later.

Actually, this is a pretty specious “argument” - although it seems to be perfectly reasonable at the first glance, all you have to do is to scratch it a bit, and,at this point, its logical fallacy becomes obvious. We are going to see it shortly

Please take what you wrote in that post, file it away somewhere with a reminder
to look at it 15 years from now and have a good laugh. API’s should never
be limited to one’s imagination of what is possible! There should be no limits

Some things are just not going to change with time. For example, I can assure you that we are NOT going to see a device that can transmit data faster than a speed of light, so that a receiver may get a message before the sender even starts transmitting it, effectively turning the entire concept of causality upside down. Similarly, no matter how far the technology advances, you are not going to consider the scenario of the same macroscopic object occupying 2 distinct positions in space at precisely the same moment of time (unless you happen to be schizophrenic,of course - then only sky is the limit) .

Our example of the CPU that may dynamically reconfigure itself at the runtime without resetting itself (at least as far a software that it executes is concerned) firmly falls into the same class of “solutions”.

Why?

Simply because then you are going to get, at least from the software’s perspective, a “moody CPU” that may, solely upon its own whim, give different interpretations of exactly the same binary instruction (i.e. before and after self-reconfiguration). How can one possibly write software for a CPU like that???

Anton Bassov