I'm using WinDbg to dump the contents of the IDT and I would like to know which interrupt number represents the Real Time Clock Interrupt in this table of things ? I've ran the !idt -a command to dump the contents of the IDT in Windbg.But cannot tell which row belongs to the RTC interrupt.
You may have to Provide a bit more Detailed information on what you have done and where you are stuck
As is Your Query will not attract clear answers
for starters have you dumped the the Interrupt Descriptor tables
using the provided bang command !idt with its arguments and not satisficed with the results ?
0: kd> .shell -ci "!idt" grep -i clock
<.shell waiting 10 second(s) for process>
d1: fffff8033cf51908 hal!HalpTimerClockInterrupt (KINTERRUPT fffff8033d725100)
d2: fffff8033cf51910 hal!HalpTimerClockIpiRoutine (KINTERRUPT fffff8033d725000)
.shell: Process exited
0: kd>
have you looked at !timer command does it provide what you are looking for ?
0: kd> !timer
Dump system timers
Interrupt time: 26a78346 00000515 [11/27/2021 12:49:47.524]
List Timer Interrupt Low/High Fire Time DPC/thread
PROCESSOR 0 (nt!_KTIMER_TABLE fffff80339a7a800)
0 ffffc388b8805180 27d3e28b 00000515 [11/27/2021 12:49:49.493] thread ffffc388b8805080
you should also be aware on the newer os these are shadows due to the ongoing security hardening of operating systems.
Related
I'm trying to disable all interrupts including NMI's on a single core in a processor and put that core into an infinite loop with a JMP instruction targeting itself (bytecode 0xEBFE) I tried this with the following machine code:
cli
in al, 0x70
mov bl, 0x80
or al, bl
out 0x70, al
jmp self (0xEBFE)
I assumed that disabling NMI interrupts would also disable the watchdog since according to this link the watchdog timer is an NMI interrupt, but what happened when I ran this code is after around 5 seconds my computer bugchecked with code 0x101 CLOCK_WATCHDOG_TIMEOUT. I'm wondering if windows notices that I've disabled NMI interrupts and then re-enables them before initiating the kernel panic. Does anyone know how to disable the watchdog timer in windows 7?
I don't think the NMIs are at fault here.
External NMIs are obsolete, they are hard to route in an SMP system. That watchdog timer is also obsolete, it was either a secondary PIT or a limited fourth channel of the primary PIT:
----------P00440047--------------------------
PORT 0044-0047 - Microchannel - PROGRAMMABLE INTERVAL TIMER 2
SeeAlso: PORT 0040h,PORT 0048h
0044 RW PIT counter 3 (PS/2)
used as fail-safe timer. generates an NMI on time out.
for user generated NMI see at 0462.
0047 -W PIT control word register counter 3 (PS/2, EISA)
bit 7-6 = 00 counter 3 select
= 01 reserved
= 10 reserved
= 11 reserved
bit 5-4 = 00 counter latch command counter 3
= 01 read/write counter bits 0-7 only
= 1x reserved
bit 3-0 = 00
----------P0048004B--------------------------
PORT 0048-004B - EISA - PROGRAMMABLE INTERVAL TIMER 2
Note: this second timer is also supported by many Intel chipsets
SeeAlso: PORT 0040h,PORT 0044h
0048 RW EISA PIT2 counter 3 (Watchdog Timer)
0049 ?? EISA 8254 timer 2, not used (counter 4)
004A RW EISA PIT2 counter 5 (CPU speed control)
004B -W EISA PIT2 control word
These hardware is gone, it's not present on modern systems. I've tested my machine and I don't have it.
Intel chipsets don't have it:
There is only the primary PIT.
Modern timers are the LAPIC timer and the HPET (Linux did even resort to using the PMC registers).
Windows does support an HW WDT, in fact Microsoft went as long as defining an ACPI extension: the WDAT table.
This WDT however can only reboot or shutdown the system, in hardware, without the intervention of the software.
// Configures the watchdog hardware to perform a reboot
// when it is fired.
//
#define WATCHDOG_ACTION_SET_REBOOT 0x11
//
// Determines if the watchdog hardware is configured to perform
// a system shutdown when fired.
//
#define WATCHDOG_ACTION_QUERY_SHUTDOWN 0x12
//
// Configures the watchdog hardware to perform a system shutdown
// when fired.
//
#define WATCHDOG_ACTION_SET_SHUTDOWN 0x13
Microsoft set quite a quit of requirement for this WDT since it must be setup as early as possible in the boot process, before the PnP enumeration (i.e. PCI(e) enumeration).
This is not the timer that bugchecked your system.
By the way, I don't have this timer (my system is missing the WDAT table) and I don't expect it to be found on client hardware.
The bugcheck 0x101 is due to a software WDT, it is raised inside a function in ntoskrnl.exe.
This function is called by KeUpdateRunTime and by another chain of calls starting in DriverEntry:
According to Windows Internals, KeUpdateRunTime is used to update the internal ticks counting of Windows.
I'd expect only a single logical processor to be put in charge of that, though I'm not sure of how exactly Windows housekeeps time.
I'd also expect this software WDT to be implemented in a master-slave fashion: each CPU increments its own counter and a designed CPU check the counters periodically (or any equivalent implementation).
This seems to be suggested by the wording of the documentation of the 0x101 bugcheck:
The CLOCK_WATCHDOG_TIMEOUT bug check has a value of 0x00000101. This indicates that an expected clock interrupt on a secondary processor, in a multi-processor system, was not received within the allocated interval.
Again, I'm not an expert on this part of Windows (The user MdRm, probably is) and this may be utterly wrong, but if it isn't you probably are better of following Alex's advice and boot with one less logical CPU.
You can then execute code on that CPU with an INIT-SIPI-SIPI sequence as described on the Intel's manual but you must be careful because the issuing processor is using paging while the sleeping one is not yet (the processor will start up in real-mode).
Initialising a CPU may be a little cumbersome but not too much after all.
Stealing it may result in other problems besides the WDT, for example if Windows has routed an interrupt to that processor only.
I don't know if there is driver API to unregister a logical processor, I found nothing looking at the exports of hal.dll and ntoskrnl.exe.
I have been trying to understand how do h/w interrupts end up in some user space code, through the kernel.
My research led me to understand that:
1- An external device needs attention from CPU
2- It signals the CPU by raising an interrupt (h/w trance to cpu or bus)
3- The CPU asserts, saves current context, looks up address of ISR in the
interrupt descriptor table (vector)
4- CPU switches to kernel (privileged) mode and executes the ISR.
Question #1: How did the kernel store ISR address in interrupt vector table? It might probably be done by sending the CPU some piece of assembly described in the CPUs user manual? The more detail on this subject the better please.
In user space how can a programmer write a piece of code that listens to a h/w device notifications?
This is what I understand so far.
5- The kernel driver for that specific device has now the message from the device and is now executing the ISR.
Question #3:If the programmer in user space wanted to poll the device, I would assume this would be done through a system call (or at least this is what I understood so far). How is this done? How can a driver tell the kernel to be called upon a specific systemcall so that it can execute the request from the user? And then what happens, how does the driver gives back the requested data to user space?
I might be completely off track here, any guidance would be appreciated.
I am not looking for specific details answers, I am only trying to understand the general picture.
Question #1: How did the kernel store ISR address in interrupt vector table?
Driver calls request_irq kernel function (defined in include/linux/interrupt.h and in kernel/irq/manage.c), and Linux kernel will register it in right way according to current CPU/arch rules.
It might probably be done by sending the CPU some piece of assembly described in the CPUs user manual?
In x86 Linux kernel stores ISR in Interrupt Descriptor Table (IDT), it format is described by vendor (Intel - volume 3) and also in many resources like http://en.wikipedia.org/wiki/Interrupt_descriptor_table and http://wiki.osdev.org/IDT and http://phrack.org/issues/59/4.html and http://en.wikibooks.org/wiki/X86_Assembly/Advanced_Interrupts.
Pointer to IDT table is registered in special CPU register (IDTR) with special assembler commands: LIDT and SIDT.
If the programmer in user space wanted to poll the device, I would assume this would be done through a system call (or at least this is what I understood so far). How is this done? How can a driver tell the kernel to be called upon a specific systemcall so that it can execute the request from the user? And then what happens, how does the driver gives back the requested data to user space?
Driver usually registers some device special file in /dev; pointers to several driver functions are registered for this file as "File Operations". User-space program opens this file (syscall open), and kernels calls device's special code for open; then program calls poll or read syscall on this fd, kernel will call *poll or *read of driver's file operations (http://www.makelinux.net/ldd3/chp-3-sect-7.shtml). Driver may put caller to sleep (wait_event*) and irq handler will wake it up (wake_up* - http://www.makelinux.net/ldd3/chp-6-sect-2 ).
You can read more about linux driver creation in book LINUX DEVICE DRIVERS (2005) by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman: https://lwn.net/Kernel/LDD3/
Chapter 3: Char Drivers https://lwn.net/images/pdf/LDD3/ch03.pdf
Chapter 10: Interrupt Handling https://lwn.net/images/pdf/LDD3/ch10.pdf
I'm working on the linux kernel 3.10 patched with LITMUS^RT, a real-time extension with a focus on multiprocessor real-time scheduling and synchronization.
My aim is to write a scheduler that allows a task to migrate from a cpu to another when preempted and only when particular conditions are met. My current implementation is affected by deadlock beetwen cpus as shown by the following error:
Setting up rt task parameters for process 1622.
[ INFO: inconsistent lock state ]
3.10.5-litmus2013.1 #105 Not tainted
---------------------------------
inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
rtspin/1620 [HC0[0]:SC0[0]:HE1:SE1] takes:
(&rq->lock){?.-.-.}, at: [<ffffffff8155f0d5>] __schedule+0x175/0xa70
{IN-HARDIRQ-W} state was registered at:
[<ffffffff8107832a>] __lock_acquire+0x86a/0x1e90
[<ffffffff81079f65>] lock_acquire+0x95/0x140
[<ffffffff81560fc6>] _raw_spin_lock+0x36/0x50
[<ffffffff8105e231>] scheduler_tick+0x61/0x210
[<ffffffff8103f112>] update_process_times+0x62/0x80
[<ffffffff81071677>] tick_periodic+0x27/0x70
[<ffffffff8107174b>] tick_handle_periodic+0x1b/0x70
[<ffffffff810042d0>] timer_interrupt+0x10/0x20
[<ffffffff810849fd>] handle_irq_event_percpu+0x6d/0x260
[<ffffffff81084c33>] handle_irq_event+0x43/0x70
[<ffffffff8108778c>] handle_level_irq+0x6c/0xc0
[<ffffffff81003a89>] handle_irq+0x19/0x30
[<ffffffff81003925>] do_IRQ+0x55/0xd0
[<ffffffff81561cef>] ret_from_intr+0x0/0x13
[<ffffffff8108615a>] __setup_irq+0x20a/0x4e0
[<ffffffff81086473>] setup_irq+0x43/0x90
[<ffffffff8184fb5f>] setup_default_timer_irq+0x12/0x14
[<ffffffff8184fb78>] hpet_time_init+0x17/0x19
[<ffffffff8184fb46>] x86_late_time_init+0xa/0x11
[<ffffffff8184ecd1>] start_kernel+0x270/0x2e0
[<ffffffff8184e5a3>] x86_64_start_reservations+0x2a/0x2c
[<ffffffff8184e66c>] x86_64_start_kernel+0xc7/0xca
irq event stamp: 8886
hardirqs last enabled at (8885): [<ffffffff8108dd6b>] rcu_note_context_switch+0x8b/0x2d0
hardirqs last disabled at (8886): [<ffffffff81561052>] _raw_spin_lock_irq+0x12/0x50
softirqs last enabled at (8880): [<ffffffff81037125>] __do_softirq+0x195/0x2b0
softirqs last disabled at (8857): [<ffffffff8103738d>] irq_exit+0x7d/0x90
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(&rq->lock);
<Interrupt>
lock(&rq->lock);
*** DEADLOCK ***
1 lock held by rtspin/1620:
#0: (&rq->lock){?.-.-.}, at: [<ffffffff8155f0d5>] __schedule+0x175/0xa70
stack backtrace:
CPU: 1 PID: 1620 Comm: rtspin Not tainted 3.10.5-litmus2013.1 #105
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
ffffffff81bc4cc0 ffff88001cdf3aa8 ffffffff8155ae1e ffff88001cdf3af8
ffffffff81557f39 0000000000000000 ffff880000000001 ffff880000000001
0000000000000000 ffff88001c5ec280 ffffffff810750d0 0000000000000002
Call Trace:
[<ffffffff8155ae1e>] dump_stack+0x19/0x1b
[<ffffffff81557f39>] print_usage_bug+0x1f7/0x208
[<ffffffff810750d0>] ? print_shortest_lock_dependencies+0x1c0/0x1c0
[<ffffffff81075ead>] mark_lock+0x2ad/0x320
[<ffffffff81075fd0>] mark_held_locks+0xb0/0x120
[<ffffffff8129bf71>] ? pfp_schedule+0x691/0xba0
[<ffffffff810760f2>] trace_hardirqs_on_caller+0xb2/0x210
[<ffffffff8107625d>] trace_hardirqs_on+0xd/0x10
[<ffffffff8129bf71>] pfp_schedule+0x691/0xba0
[<ffffffff81069e70>] pick_next_task_litmus+0x40/0x500
[<ffffffff8155f17a>] __schedule+0x21a/0xa70
[<ffffffff8155f9f4>] schedule+0x24/0x70
[<ffffffff8155d1bc>] schedule_timeout+0x14c/0x200
[<ffffffff8105e3ed>] ? get_parent_ip+0xd/0x50
[<ffffffff8105e589>] ? sub_preempt_count+0x69/0xf0
[<ffffffff8155ffab>] wait_for_completion_interruptible+0xcb/0x140
[<ffffffff81060e60>] ? try_to_wake_up+0x470/0x470
[<ffffffff8129266f>] do_wait_for_ts_release+0xef/0x190
[<ffffffff81292782>] sys_wait_for_ts_release+0x22/0x30
[<ffffffff81562552>] system_call_fastpath+0x16/0x1b
At this point I suppose I see two possible approaches to follow to solve this problem:
Release the lock to the current cpu before migrating to the target cpu using the kernel's functions. LITMUS^RT provides a callback in which I can decide which task will execute:
static struct task_struct* pfp_schedule(struct task_struct * prev) {
[...]
if(is_preempted(prev) {
// release lock on current cpu
migrate_to_another_cpu();
}
[...]
}
What I think I must do is to release the current lock before the call to migrate_to_another_cpu function, but I still haven't found any way of doing that.
The scheduler that I want to implement allows only one task migration at a time, therefore it's theoretically impossible to have a deadlock. For some reasons though the execution of my task set fails and I get the error listed above which I think is identified during some kind of preliminary analisys performed by the linux kernel. This, however is a potential deadlock, it's kind of a warning, and I would like to let my task set to continue its normal execution ignoring it.
Long story short, does anyone know if one of these solutions is possible and, if yes, how to implement it?
Thanks in advance!
P.S.: tips or better ideas are very welcome! ;-)
I am working on an embedded Linux system, and I need to shut the system down when a particular IRQ handler runs. I don't have a lot of time (tens of milliseconds). I was using emergency_restart(), but I now need to perform some work (writing shutdown-related info to flash) that cannot be done from an interrupt context because the flash driver will not support it.
Can anyone recommend a good way to accomplish this? I would love to properly kill my user-space applications by sending them a signal so that they can do the flash write. How do I do this? I suppose, as an alternative, I could have a high priority process that sits, waiting on a semaphore that my interrupt generates... What are my options? Thanks in advance!
That is exactly what signals are for. If one of the existing signals don't make sense (see man 7 signal), use one of the user definable signals:
#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */
#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */
One of our legacy applications is producing resource leaks on 1 specific machine. Over time the overall processor usage increases until the application is closed and restarted.
Using perfmon I found a direct correlation between the process's handle count and the processor usage. This count went up into the thousands and I used SysInternal's handle to expose that all the extra handles (at least during the process running this afternoon when I ran handle) had a path of \Device\00000066.
I want to learn how to discover more information about exactly what device the device path is referring to so we know where to go from here. I have strong suspicions that the device is a PIN pad (used during debit transactions), but need proof.
Windows XP sp3.
Resolution
After Seva Titov's advice helped me identify it was a USB device, I had one main suspect: a cash drawer. We had the client unplug it and use it manually for a few hours: no constant increase in handles. I looked through that project's code and the developer neglected to close handles to the device after obtaining them. The rapid increase in handles was due to a timer that checked the drawer's status after it was opened to determine when the user had closed it.
Here is how you can get more information on the kernel directory object:
Install LiveKd, install Windows Debugging Tools
Launch LiveKd in the directory that contains kd.exe
Inside LiveKd prompt type this:
!object \device\00000066
Then use the value that it shows for the object (the first it prints) with !devobj command.
This is the example I did on my system -- I picked up a random device with name \device\0000006a as an example (just to confuse you :->)
0: kd> !object \device\0000006a
Object: fffffa8007959630 Type: (fffffa8006bce2d0) Device
ObjectHeader: fffffa8007959600 (new version)
HandleCount: 0 PointerCount: 6
Directory Object: fffff8a00000b8f0 Name: 0000006a
0: kd> !devobj fffffa8007959630
Device object (fffffa8007959630) is for:
0000006a \Driver\ACPI DriverObject fffffa8006b25d00
Current Irp 00000000 RefCount 1 Type 00000032 Flags 00003040
Dacl fffff9a100092d31 DevExt fffffa800792e7d0 DevObjExt fffffa8007959780 DevNode fffffa800796db10
ExtensionFlags (0x00000800)
Unknown flags 0x00000800
AttachedDevice (Upper) fffffa800907d040 \Driver\i8042prt
Device queue is not busy.
The \driver should give you a hint on what the device is.