Xen PV Guest interrupt

紧接这一篇:

http://blog.csdn.net/snailhit/archive/2010/12/28/6101827.aspx

 

 

当在PV Guest里运行cat /proc/interrupts查看中断设置情况是,会发现中断号不是从0开始的,而是从256开始的。典型的如下:

 

           CPU0             
256:     111925     Dynamic-irq  timer0 (VM只有一个VCPU,若是SMP-VM,则有timer1, timer2, ...)
257:          0     Dynamic-irq  resched0
258:          0     Dynamic-irq  callfunc0

-----

... timer1, resched1, callfunc1, ...

-----
259:        270     Dynamic-irq  xenbus
260:       1801     Dynamic-irq  xencons
261:       3616     Dynamic-irq  blkif
262:       7756     Dynamic-irq  eth0
NMI:         0
LOC:         0
ERR:         0
MIS:         0

 

都是dynamic-irq,那么physical irq跑哪儿去了...? 原来,在PV guest中,所有的phyisical IRQ都被cut掉了,所有的都有dynamic IRQ来负责:

#define NR_DYNIRQS  256

#define NR_IRQS   (NR_PIRQS + NR_DYNIRQS)

 

在domain 0下运行 cat /proc/interrupts:

 

           CPU0       CPU1       CPU2       CPU3      
  1:       3196          0          0          0      Phys-level     i8042 (键盘..?)
  6:          3          0          0          0      Phys-level     floppy
  8:          0          0          0          0      Phys-level     rtc0 (rtc时钟)
 12:          4          0          0          0      Phys-level     i8042 (鼠标..?)
 14:      21648      26431          0          0      Phys-level     ata_piix (硬盘)
 15:     317748      19659          0          0      Phys-level     ata_piix
 16:        407          0          0          0      Phys-level     ehci_hcd:usb2, uhci_hcd:usb3, uhci_hcd:usb6, HDA Intel
 17:          0          0          0          0      Phys-level     uhci_hcd:usb4, uhci_hcd:usb7
 18:      73797          0          0          0      Phys-level     ehci_hcd:usb1, uhci_hcd:usb5, uhci_hcd:usb8, ata_piix
------------

439:      23348          0          0          0      Phys-level     peth0
440:   30292618     929005     656343     640930   Dynamic-percpu    timer
441:     338983     738843     598292     605525   Dynamic-percpu    resched
442:         23        196        233        221   Dynamic-percpu    callfunc
443:      23559       2526       1132        865   Dynamic-percpu    call1func
444:          0          0          0          0   Dynamic-percpu    reboot
445:       1144        476        212        145   Dynamic-percpu    spinlock
446:          0          0          0          0   Dynamic-level     mce
447:        283          0          0          0   Dynamic-level     console
448:         78        463         61          0   Dynamic-level     xenbus

--
449:        804        987          0          0   Dynamic-level     blkif-backend
450:       5731       1906          0          0   Dynamic-level     vif1.0
--

451 .... blkif-backend

450 .... vif2.0

--

NMI:          0          0          0          0   Non-maskable interrupts
RES:     338983     738844     598293     605526   Rescheduling interrupts
CAL:      23582       2722       1365       1086   Function call interrupts
MCE:          0          0          0          0   Machine check exceptions
MCP:          1          1          1          1   Machine check polls

 

看Guest启动后,如何初始化irq_descriptor[NR_IRQS] (linux/driver/xen/core/evtchn.c, xen_init_IRQ):

 /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
 for (i = DYNIRQ_BASE; i < (DYNIRQ_BASE + NR_DYNIRQS); i++) {
  irq_bindcount[i] = 0;

  irq_desc[i].status = IRQ_DISABLED|IRQ_NOPROBE;
  irq_desc[i].action = NULL;
  irq_desc[i].depth = 1;
  irq_desc[i].chip = &dynirq_type;
 }

 

static struct hw_interrupt_type dynirq_type = {
 .typename = "Dynamic-irq",
 .startup  = startup_dynirq,
 .shutdown = shutdown_dynirq,
 .enable   = enable_dynirq,
 .disable  = disable_dynirq,
 .ack      = ack_dynirq,
 .end      = end_dynirq,
 .set_affinity = set_affinity_irq,
 .retrigger = resend_irq_on_evtchn,
};

-----------------------

对于physical IRQ:

 /* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
 for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_PIRQS); i++) {
  irq_bindcount[i] = 1;

  if (!identity_mapped_irq(i))
   continue;

#ifdef RTC_IRQ
  /* If not domain 0, force our RTC driver to fail its probe. */
  if (i - PIRQ_BASE == RTC_IRQ && !is_initial_xendomain())
   continue;
#endif

  irq_desc[i].status = IRQ_DISABLED;
  irq_desc[i].action = NULL;
  irq_desc[i].depth = 1;
  irq_desc[i].chip = &pirq_type;
 }

 

static struct hw_interrupt_type pirq_type = {
 .typename = "Phys-irq",
 .startup  = startup_pirq,
 .shutdown = shutdown_pirq,
 .enable   = enable_pirq,
 .disable  = disable_pirq,
 .ack      = ack_pirq,
 .end      = end_pirq,
 .set_affinity = set_affinity_irq,
 .retrigger = resend_irq_on_evtchn,
};

 

对于不是driver domain的guest VM,rtc(real-time-clock)直接被禁掉了,时钟由VIRQ_TIMER来接管 (见linux/arch/arch/i386/kernel/time-xen.c, local_setup_timer)

 

physical irq 通过evtchn_register_pirq来注册

--------------------------------------

为什么是dynamic的:每一次分配,都要先去找unbound irq

static int find_unbound_irq(void)
{
 static int warned;
 int irq;

 for (irq = DYNIRQ_BASE; irq < (DYNIRQ_BASE + NR_DYNIRQS); irq++)
  if (irq_bindcount[irq] == 0)
   return irq;

 return -ENOSPC;
}

 

找到之后,通过hypercall想去和VM的evtchn来bind (有Xen来做的事情),结果Xen也要dynamic的找get_free_port

for ( port = 0; port_is_valid(d, port); port++ )
        if ( evtchn_from_port(d, port)->state == ECS_FREE )
            return port;

 

 

 

 

你可能感兴趣的:(Xen PV Guest interrupt)