본문 바로가기

Programming

QEMU and timer interrupt

별건아니지만 QEMU 에서는 외부반응이 전혀 없을때는 LOC 타이머 인터럽트가 거의 발생하지 않는다. VM웨어의 경우와 비교해보면, 일정시간이 지나면 무조건 해당 시간만큼 값이 증가해있는데, QEMU 의 경우 아무동작을 하지 않는동안은 Timer 틱이 증가하지 않는걸 확인 할 수 있다.  반면 키보드를 계속 두드리거나 뭔가를 한뒤에 타이머카운트를 보면 많이 증가하는것을 볼 수 있다.

또한 바닐라커널과 Ubuntu 를 비교해보면 기본적으로 설치되는 인터럽트핸들러가 매우 차이가 나는것을 볼 수 있다.


(QEMU)

/proc # cat interrupts 

           CPU0       

  0:        374   IO-APIC-edge      timer

  1:         10   IO-APIC-edge      i8042

  4:       9317   IO-APIC-edge      serial

  8:          1   IO-APIC-edge      rtc0

  9:          0   IO-APIC-fasteoi   acpi

 12:        125   IO-APIC-edge      i8042

 14:          0   IO-APIC-edge      ata_piix

 15:          9   IO-APIC-edge      ata_piix

NMI:          0   Non-maskable interrupts

LOC:       4599   Local timer interrupts

SPU:          0   Spurious interrupts



(Ubuntu)

daehee@ubuntu:~$ cat /proc/interrupts 

            CPU0       

   0:         46   IO-APIC-edge      timer

   1:      37666   IO-APIC-edge      i8042

   3:         12   IO-APIC-edge    

   4:     239106   IO-APIC-edge    

   6:          2   IO-APIC-edge      floppy

   7:          0   IO-APIC-edge      parport0

   8:          1   IO-APIC-edge      rtc0

   9:          0   IO-APIC-fasteoi   acpi

  12:     128924   IO-APIC-edge      i8042

  14:          0   IO-APIC-edge      ata_piix

  15:     322770   IO-APIC-edge      ata_piix

  16:       2719   IO-APIC-fasteoi   vmwgfx, snd_ens1371

  17:     119874   IO-APIC-fasteoi   ehci_hcd:usb1, ioc0

  18:         70   IO-APIC-fasteoi   uhci_hcd:usb2

  19:     210682   IO-APIC-fasteoi   eth0

  40:          0   PCI-MSI-edge      PCIe PME, pciehp

  41:          0   PCI-MSI-edge      PCIe PME, pciehp

  42:          0   PCI-MSI-edge      PCIe PME, pciehp

  43:          0   PCI-MSI-edge      PCIe PME, pciehp

  44:          0   PCI-MSI-edge      PCIe PME, pciehp

  45:          0   PCI-MSI-edge      PCIe PME, pciehp

  46:          0   PCI-MSI-edge      PCIe PME, pciehp

  47:          0   PCI-MSI-edge      PCIe PME, pciehp

  48:          0   PCI-MSI-edge      PCIe PME, pciehp

  49:          0   PCI-MSI-edge      PCIe PME, pciehp

  50:          0   PCI-MSI-edge      PCIe PME, pciehp

  51:          0   PCI-MSI-edge      PCIe PME, pciehp

  52:          0   PCI-MSI-edge      PCIe PME, pciehp

  53:          0   PCI-MSI-edge      PCIe PME, pciehp

  54:          0   PCI-MSI-edge      PCIe PME, pciehp

  55:          0   PCI-MSI-edge      PCIe PME, pciehp

  56:          0   PCI-MSI-edge      PCIe PME, pciehp

  57:          0   PCI-MSI-edge      PCIe PME, pciehp

  58:          0   PCI-MSI-edge      PCIe PME, pciehp

  59:          0   PCI-MSI-edge      PCIe PME, pciehp

  60:          0   PCI-MSI-edge      PCIe PME, pciehp

  61:          0   PCI-MSI-edge      PCIe PME, pciehp

  62:          0   PCI-MSI-edge      PCIe PME, pciehp

  63:          0   PCI-MSI-edge      PCIe PME, pciehp

  64:          0   PCI-MSI-edge      PCIe PME, pciehp

  65:          0   PCI-MSI-edge      PCIe PME, pciehp

  66:          0   PCI-MSI-edge      PCIe PME, pciehp

  67:          0   PCI-MSI-edge      PCIe PME, pciehp

  68:          0   PCI-MSI-edge      PCIe PME, pciehp

  69:          0   PCI-MSI-edge      PCIe PME, pciehp

  70:          0   PCI-MSI-edge      PCIe PME, pciehp

  71:          0   PCI-MSI-edge      PCIe PME, pciehp

  72:          6   PCI-MSI-edge      vmw_vmci

  73:          0   PCI-MSI-edge      vmw_vmci

 NMI:          0   Non-maskable interrupts

 LOC:   11552063   Local timer interrupts

 SPU:          0   Spurious interrupts

 PMI:          0   Performance monitoring interrupts

 IWI:     280299   IRQ work interrupts

 RTR:          0   APIC ICR read retries

 RES:          0   Rescheduling interrupts

 CAL:          0   Function call interrupts

 TLB:          0   TLB shootdowns

 TRM:          0   Thermal event interrupts

 THR:          0   Threshold APIC interrupts

 MCE:          0   Machine check exceptions

 MCP:       1102   Machine check polls

 ERR:          0

 MIS:          0



인터럽트의 경우 kernel api 중에 request_irq() 를 통해서 IDT 에 함수포인터를 등록시키는 방식으로 등록하는데, 이때 fast irq 인지 slow irq 인지, /dev/random 쪽 노이즈에 해당 인터럽트를 활용할지 등등의 플래그 및 파라미터를 함께 전달해준다.


또한 요즘의 인터럽트 핸들링 방식에서는 직접적으로 cli-sti 로 critical section 을 잡지 않고 하이레벨 매크로나 함수를 사용한다.  이는 multi-core 시스템에서 어쩔때는 cli 가 프로세서 전역적으로 인터럽트 마스킹을 할 수도 있고 어쩔때는 current core 에만 작용하는 경우등, 고려하기 민감한 경우가 많아서 그렇다. 인터럽트 마스킹뿐만 아니라 커널내부의 코드에서는 concurrency 를 잘 고려해야하기때문에, spinlock, mutex 등이 함께 사용된다.


또한 참고로 프로세스의 커널모드스택이 따로 존재하듯이 인터럽트스택또한 따로 존재한다.  그리고 디버깅해본 결과에따르면 이 인터럽트 스택은 프로세스 컨텍스트와 무관하게 항상 고정된 위치를 사용하는것 같다...