ia64/xen-unstable

changeset 7634:65c3b9382caa

This patch is to remove the pit_timer when the vmx domain is
inactive to save HV external IRQ caused by ac_time and some cleanup for
ioapic in HV.
Thx,eddie

Signed-off-by: Eddie Dong <eddie.dong@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Nov 05 11:26:29 2005 +0100 (2005-11-05)
parents b180310a0d2c
children 0cae0c6436f5
files tools/ioemu/hw/pc.c tools/ioemu/target-i386-dm/Makefile tools/ioemu/target-i386-dm/helper2.c xen/arch/x86/dm/i8259.c xen/arch/x86/vmx.c xen/arch/x86/vmx_intercept.c xen/arch/x86/vmx_io.c xen/arch/x86/vmx_vlapic.c xen/arch/x86/vmx_vmcs.c xen/include/asm-x86/vmx.h xen/include/asm-x86/vmx_virpit.h xen/include/asm-x86/vmx_vlapic.h xen/include/asm-x86/vmx_vmcs.h xen/include/public/io/vmx_vlapic.h xen/include/public/io/vmx_vpic.h
line diff
     1.1 --- a/tools/ioemu/hw/pc.c	Sat Nov 05 11:23:02 2005 +0100
     1.2 +++ b/tools/ioemu/hw/pc.c	Sat Nov 05 11:26:29 2005 +0100
     1.3 @@ -547,9 +547,6 @@ void pc_init(int ram_size, int vga_ram_s
     1.4                  pci_pcnet_init(pci_bus, &nd_table[i]); 
     1.5          }
     1.6          pci_piix3_ide_init(pci_bus, bs_table);
     1.7 -#ifdef APIC_SUPPORT
     1.8 -        IOAPICInit();
     1.9 -#endif
    1.10      } else {
    1.11          nb_nics1 = nb_nics;
    1.12          if (nb_nics1 > NE2000_NB_MAX)
     2.1 --- a/tools/ioemu/target-i386-dm/Makefile	Sat Nov 05 11:23:02 2005 +0100
     2.2 +++ b/tools/ioemu/target-i386-dm/Makefile	Sat Nov 05 11:26:29 2005 +0100
     2.3 @@ -187,7 +187,7 @@ endif
     2.4  
     2.5  #########################################################
     2.6  
     2.7 -DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DAPIC_SUPPORT
     2.8 +DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
     2.9  LIBS+=-lm -L../../libxc -lxenctrl
    2.10  ifndef CONFIG_USER_ONLY
    2.11  LIBS+=-lz
    2.12 @@ -245,7 +245,6 @@ endif
    2.13  # must use static linking to avoid leaving stuff in virtual address space
    2.14  VL_OBJS=vl.o exec.o monitor.o osdep.o block.o readline.o pci.o console.o 
    2.15  VL_OBJS+=block-cow.o block-qcow.o block-vmdk.o block-cloop.o aes.o
    2.16 -VL_OBJS+=ioapic.o
    2.17  #VL_OBJS+= block-cloop.o
    2.18  
    2.19  SOUND_HW = sb16.o
     3.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Sat Nov 05 11:23:02 2005 +0100
     3.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Sat Nov 05 11:26:29 2005 +0100
     3.3 @@ -456,17 +456,10 @@ int main_loop(void)
     3.4  #endif
     3.5  
     3.6  		main_loop_wait(0);
     3.7 -#ifdef APIC_SUPPORT
     3.8 -		ioapic_update_EOI();
     3.9 -#endif
    3.10          tun_receive_handler(&rfds);
    3.11          if ( FD_ISSET(evtchn_fd, &rfds) ) {
    3.12              cpu_handle_ioreq(env);
    3.13          }
    3.14 -#ifdef APIC_SUPPORT
    3.15 -		if (ioapic_has_intr())
    3.16 -                    do_ioapic();
    3.17 -#endif
    3.18  		if (env->send_event) {
    3.19  			struct ioctl_evtchn_notify notify;
    3.20  			notify.port = ioreq_local_port;
     4.1 --- a/xen/arch/x86/dm/i8259.c	Sat Nov 05 11:23:02 2005 +0100
     4.2 +++ b/xen/arch/x86/dm/i8259.c	Sat Nov 05 11:26:29 2005 +0100
     4.3 @@ -525,3 +525,16 @@ int is_pit_irq(struct vcpu *v, int irq, 
     4.4  
     4.5      return (irq == pit_vec);
     4.6  }
     4.7 +
     4.8 +int is_irq_enabled(struct vcpu *v, int irq)
     4.9 +{
    4.10 +    struct vmx_virpic *vpic=&v->domain->arch.vmx_platform.vmx_pic;
    4.11 +        
    4.12 +    if ( irq & 8 ) {
    4.13 +        return !( (1 << (irq&7)) & vpic->pics[1].imr);
    4.14 +    }
    4.15 +    else {
    4.16 +        return !( (1 << irq) & vpic->pics[0].imr);
    4.17 +    }
    4.18 +}
    4.19 +
     5.1 --- a/xen/arch/x86/vmx.c	Sat Nov 05 11:23:02 2005 +0100
     5.2 +++ b/xen/arch/x86/vmx.c	Sat Nov 05 11:26:29 2005 +0100
     5.3 @@ -43,6 +43,8 @@
     5.4  #endif
     5.5  #include <public/sched.h>
     5.6  #include <public/io/ioreq.h>
     5.7 +#include <public/io/vmx_vpic.h>
     5.8 +#include <public/io/vmx_vlapic.h>
     5.9  
    5.10  int hvm_enabled;
    5.11  
    5.12 @@ -85,6 +87,8 @@ void vmx_final_setup_guest(struct vcpu *
    5.13  
    5.14  void vmx_relinquish_resources(struct vcpu *v)
    5.15  {
    5.16 +    struct vmx_virpit *vpit;
    5.17 +    
    5.18      if ( !VMX_DOMAIN(v) )
    5.19          return;
    5.20  
    5.21 @@ -96,7 +100,12 @@ void vmx_relinquish_resources(struct vcp
    5.22  
    5.23      destroy_vmcs(&v->arch.arch_vmx);
    5.24      free_monitor_pagetable(v);
    5.25 -    rem_ac_timer(&v->domain->arch.vmx_platform.vmx_pit.pit_timer);
    5.26 +    vpit = &v->domain->arch.vmx_platform.vmx_pit;
    5.27 +    if ( vpit->ticking && active_ac_timer(&(vpit->pit_timer)) )
    5.28 +        rem_ac_timer(&vpit->pit_timer);
    5.29 +    if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) ) {
    5.30 +        rem_ac_timer(&v->arch.arch_vmx.hlt_timer);
    5.31 +    }
    5.32      if ( vmx_apic_support(v->domain) ) {
    5.33          rem_ac_timer( &(VLAPIC(v)->vlapic_timer) );
    5.34          xfree( VLAPIC(v) );
    5.35 @@ -1521,12 +1530,24 @@ static inline void vmx_do_msr_write(stru
    5.36                  (unsigned long)regs->edx);
    5.37  }
    5.38  
    5.39 -volatile unsigned long do_hlt_count;
    5.40  /*
    5.41   * Need to use this exit to reschedule
    5.42   */
    5.43  void vmx_vmexit_do_hlt(void)
    5.44  {
    5.45 +    struct vcpu *v=current;
    5.46 +    struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
    5.47 +    s_time_t   next_pit=-1,next_wakeup;
    5.48 +
    5.49 +    if ( !v->vcpu_id ) {
    5.50 +        next_pit = get_pit_scheduled(v,vpit);
    5.51 +    }
    5.52 +    next_wakeup = get_apictime_scheduled(v);
    5.53 +    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) {
    5.54 +        next_wakeup = next_pit;
    5.55 +    }
    5.56 +    if ( next_wakeup != - 1 ) 
    5.57 +        set_ac_timer(&current->arch.arch_vmx.hlt_timer, next_wakeup);
    5.58      do_block();
    5.59  }
    5.60  
     6.1 --- a/xen/arch/x86/vmx_intercept.c	Sat Nov 05 11:23:02 2005 +0100
     6.2 +++ b/xen/arch/x86/vmx_intercept.c	Sat Nov 05 11:26:29 2005 +0100
     6.3 @@ -317,27 +317,51 @@ int intercept_pit_io(ioreq_t *p)
     6.4      return 0;
     6.5  }
     6.6  
     6.7 -/* hooks function for the PIT initialization response iopacket */
     6.8 -static void pit_timer_fn(void *data)
     6.9 +/* hooks function for the HLT instruction emulation wakeup */
    6.10 +void hlt_timer_fn(void *data)
    6.11  {
    6.12 -    struct vmx_virpit *vpit = data;
    6.13 -    s_time_t   next;
    6.14 +    struct vcpu *v = data;
    6.15 +    
    6.16 +    evtchn_set_pending(v, iopacket_port(v->domain));
    6.17 +}
    6.18 +
    6.19 +static __inline__ void missed_ticks(struct vmx_virpit*vpit)
    6.20 +{
    6.21      int        missed_ticks;
    6.22  
    6.23      missed_ticks = (NOW() - vpit->scheduled)/(s_time_t) vpit->period;
    6.24 -
    6.25 -    /* Set the pending intr bit, and send evtchn notification to myself. */
    6.26 -    vpit->pending_intr_nr++; /* already set, then count the pending intr */
    6.27 -    evtchn_set_pending(vpit->v, iopacket_port(vpit->v->domain));
    6.28 -
    6.29 -    /* pick up missed timer tick */
    6.30      if ( missed_ticks > 0 ) {
    6.31          vpit->pending_intr_nr += missed_ticks;
    6.32          vpit->scheduled += missed_ticks * vpit->period;
    6.33      }
    6.34 -    next = vpit->scheduled + vpit->period;
    6.35 -    set_ac_timer(&vpit->pit_timer, next);
    6.36 -    vpit->scheduled = next;
    6.37 +}
    6.38 +
    6.39 +/* hooks function for the PIT when the guest is active */
    6.40 +static void pit_timer_fn(void *data)
    6.41 +{
    6.42 +    struct vcpu *v = data;
    6.43 +    struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
    6.44 +
    6.45 +    /* pick up missed timer tick */
    6.46 +    missed_ticks(vpit);
    6.47 +
    6.48 +    vpit->pending_intr_nr++;
    6.49 +    if ( test_bit(_VCPUF_running, &v->vcpu_flags) ) {
    6.50 +        vpit->scheduled += vpit->period;
    6.51 +        set_ac_timer(&vpit->pit_timer, vpit->scheduled);
    6.52 +    }
    6.53 +}
    6.54 +
    6.55 +void pickup_deactive_ticks(struct vmx_virpit *vpit)
    6.56 +{
    6.57 +
    6.58 +    if ( !active_ac_timer(&(vpit->pit_timer)) ) {
    6.59 +        /* pick up missed timer tick */
    6.60 +        missed_ticks(vpit);
    6.61 +    
    6.62 +        vpit->scheduled += vpit->period;
    6.63 +        set_ac_timer(&vpit->pit_timer, vpit->scheduled);
    6.64 +    }
    6.65  }
    6.66  
    6.67  /* Only some PIT operations such as load init counter need a hypervisor hook.
    6.68 @@ -359,8 +383,10 @@ void vmx_hooks_assist(struct vcpu *v)
    6.69              reinit = 1;
    6.70   
    6.71          }
    6.72 -        else
    6.73 -            init_ac_timer(&vpit->pit_timer, pit_timer_fn, vpit, v->processor);
    6.74 +        else {
    6.75 +            init_ac_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor);
    6.76 +            vpit->ticking = 1;
    6.77 +        }
    6.78  
    6.79          /* init count for this channel */
    6.80          vpit->init_val = (p->u.data & 0xFFFF) ;
    6.81 @@ -397,8 +423,6 @@ void vmx_hooks_assist(struct vcpu *v)
    6.82              break;
    6.83          }
    6.84  
    6.85 -        vpit->v = v;
    6.86 -
    6.87          vpit->scheduled = NOW() + vpit->period;
    6.88          set_ac_timer(&vpit->pit_timer, vpit->scheduled);
    6.89  
     7.1 --- a/xen/arch/x86/vmx_io.c	Sat Nov 05 11:23:02 2005 +0100
     7.2 +++ b/xen/arch/x86/vmx_io.c	Sat Nov 05 11:26:29 2005 +0100
     7.3 @@ -931,6 +931,7 @@ asmlinkage void vmx_intr_assist(void)
     7.4  
     7.5  void vmx_do_resume(struct vcpu *v)
     7.6  {
     7.7 +    struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
     7.8      vmx_stts();
     7.9  
    7.10      if (event_pending(v)) {
    7.11 @@ -939,6 +940,9 @@ void vmx_do_resume(struct vcpu *v)
    7.12          if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
    7.13              vmx_wait_io();
    7.14      }
    7.15 +    /* pick up the elapsed PIT ticks and re-enable pit_timer */
    7.16 +    if ( vpit->ticking )
    7.17 +        pickup_deactive_ticks(vpit);
    7.18  
    7.19      /* We can't resume the guest if we're waiting on I/O */
    7.20      ASSERT(!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags));
     8.1 --- a/xen/arch/x86/vmx_vlapic.c	Sat Nov 05 11:23:02 2005 +0100
     8.2 +++ b/xen/arch/x86/vmx_vlapic.c	Sat Nov 05 11:26:29 2005 +0100
     8.3 @@ -60,11 +60,20 @@ int vlapic_find_highest_irr(struct vlapi
     8.4      return result;
     8.5  }
     8.6  
     8.7 -inline int vmx_apic_support(struct domain *d)
     8.8 +int vmx_apic_support(struct domain *d)
     8.9  {
    8.10      return d->arch.vmx_platform.lapic_enable;
    8.11  }
    8.12  
    8.13 +s_time_t get_apictime_scheduled(struct vcpu *v)
    8.14 +{
    8.15 +    struct vlapic *vlapic = VLAPIC(v);
    8.16 +
    8.17 +    if ( !vmx_apic_support(v->domain) || !vlapic_lvt_timer_enabled(vlapic) )
    8.18 +        return -1;
    8.19 +    return vlapic->vlapic_timer.expires;
    8.20 +}
    8.21 +
    8.22  int vlapic_find_highest_isr(struct vlapic *vlapic)
    8.23  {
    8.24      int result;
     9.1 --- a/xen/arch/x86/vmx_vmcs.c	Sat Nov 05 11:23:02 2005 +0100
     9.2 +++ b/xen/arch/x86/vmx_vmcs.c	Sat Nov 05 11:26:29 2005 +0100
     9.3 @@ -321,6 +321,7 @@ static void vmx_do_launch(struct vcpu *v
     9.4          vlapic_init(v);
     9.5  
     9.6      vmx_set_host_env(v);
     9.7 +    init_ac_timer(&v->arch.arch_vmx.hlt_timer, hlt_timer_fn, v, v->processor);
     9.8  
     9.9      error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
    9.10      error |= __vmwrite(GUEST_LDTR_BASE, 0);
    10.1 --- a/xen/include/asm-x86/vmx.h	Sat Nov 05 11:23:02 2005 +0100
    10.2 +++ b/xen/include/asm-x86/vmx.h	Sat Nov 05 11:26:29 2005 +0100
    10.3 @@ -530,5 +530,6 @@ void store_cpu_user_regs(struct cpu_user
    10.4  
    10.5  enum { VMX_COPY_IN = 0, VMX_COPY_OUT };
    10.6  int vmx_copy(void *buf, unsigned long laddr, int size, int dir);
    10.7 +void pickup_deactive_ticks(struct vmx_virpit *vpit);
    10.8  
    10.9  #endif /* __ASM_X86_VMX_H__ */
    11.1 --- a/xen/include/asm-x86/vmx_virpit.h	Sat Nov 05 11:23:02 2005 +0100
    11.2 +++ b/xen/include/asm-x86/vmx_virpit.h	Sat Nov 05 11:26:29 2005 +0100
    11.3 @@ -8,6 +8,7 @@
    11.4  #include <xen/errno.h>
    11.5  #include <xen/ac_timer.h>
    11.6  #include <asm/vmx_vmcs.h>
    11.7 +#include <public/io/vmx_vpic.h>
    11.8  
    11.9  #define PIT_FREQ 1193181
   11.10  
   11.11 @@ -18,14 +19,15 @@
   11.12  
   11.13  struct vmx_virpit {
   11.14      /* for simulation of counter 0 in mode 2*/
   11.15 -    u32 period;		/* pit frequency in ns */
   11.16      u64 period_cycles;	                /* pit frequency in cpu cycles */
   11.17 +    u64 inject_point; /* the time inject virt intr */
   11.18      s_time_t scheduled;                 /* scheduled timer interrupt */
   11.19 +    struct ac_timer pit_timer;  /* periodic timer for mode 2*/
   11.20      unsigned int channel;  /* the pit channel, counter 0~2 */
   11.21      unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
   11.22 -    u64 inject_point; /* the time inject virt intr */
   11.23 -    struct ac_timer pit_timer;  /* periodic timer for mode 2*/
   11.24 +    u32 period;		/* pit frequency in ns */
   11.25      int first_injected;                 /* flag to prevent shadow window */
   11.26 +    int ticking;    /* indicating it is ticking */
   11.27  
   11.28      /* virtual PIT state for handle related I/O */
   11.29      int read_state;
   11.30 @@ -34,10 +36,20 @@ struct vmx_virpit {
   11.31  
   11.32      unsigned int count;  /* the 16 bit channel count */
   11.33      unsigned int init_val; /* the init value for the counter */
   11.34 -    struct vcpu *v;
   11.35  };
   11.36  
   11.37  /* to hook the ioreq packet to get the PIT initializaiton info */
   11.38  extern void vmx_hooks_assist(struct vcpu *v);
   11.39  
   11.40 +static __inline__ s_time_t get_pit_scheduled(
   11.41 +    struct vcpu *v, 
   11.42 +    struct vmx_virpit *vpit)
   11.43 +{
   11.44 +    if ( is_irq_enabled(v, 0) ) {
   11.45 +        return vpit->scheduled;
   11.46 +    }
   11.47 +    else
   11.48 +        return -1;
   11.49 +}
   11.50 +
   11.51  #endif /* _VMX_VIRPIT_H_ */
    12.1 --- a/xen/include/asm-x86/vmx_vlapic.h	Sat Nov 05 11:23:02 2005 +0100
    12.2 +++ b/xen/include/asm-x86/vmx_vlapic.h	Sat Nov 05 11:26:29 2005 +0100
    12.3 @@ -239,7 +239,8 @@ struct vlapic* apic_round_robin(struct d
    12.4                                  uint8_t dest_mode,
    12.5                                  uint8_t vector,
    12.6                                  uint32_t bitmap);
    12.7 -
    12.8 +s_time_t get_apictime_scheduled(struct vcpu *v);
    12.9  int vmx_apic_support(struct domain *d);
   12.10  
   12.11  #endif /* VMX_VLAPIC_H */
   12.12 +
    13.1 --- a/xen/include/asm-x86/vmx_vmcs.h	Sat Nov 05 11:23:02 2005 +0100
    13.2 +++ b/xen/include/asm-x86/vmx_vmcs.h	Sat Nov 05 11:26:29 2005 +0100
    13.3 @@ -99,6 +99,7 @@ struct arch_vmx_struct {
    13.4      void                    *io_bitmap_a, *io_bitmap_b;
    13.5      struct vlapic           *vlapic;
    13.6      u64                     tsc_offset;
    13.7 +    struct ac_timer         hlt_timer;  /* hlt ins emulation wakeup timer */
    13.8  };
    13.9  
   13.10  #define vmx_schedule_tail(next)         \
   13.11 @@ -116,6 +117,7 @@ struct vmcs_struct *alloc_vmcs(void);
   13.12  int modify_vmcs(struct arch_vmx_struct *arch_vmx,
   13.13                  struct cpu_user_regs *regs);
   13.14  void destroy_vmcs(struct arch_vmx_struct *arch_vmx);
   13.15 +void hlt_timer_fn(void *data);
   13.16  
   13.17  #define VMCS_USE_HOST_ENV       1
   13.18  #define VMCS_USE_SEPARATE_ENV   0
    14.1 --- a/xen/include/public/io/vmx_vlapic.h	Sat Nov 05 11:23:02 2005 +0100
    14.2 +++ b/xen/include/public/io/vmx_vlapic.h	Sat Nov 05 11:26:29 2005 +0100
    14.3 @@ -28,14 +28,6 @@
    14.4  #define VLAPIC_INT_COUNT                (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(uint64_t)))
    14.5  #define VLAPIC_INT_COUNT_32             (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(uint32_t)))
    14.6  
    14.7 -struct vapic_bus_message{
    14.8 -   uint8_t   deliv_mode:4;   /* deliver mode, including fixed, LPRI, etc */
    14.9 -   uint8_t   level:1;        /* level or edge */
   14.10 -   uint8_t   trig_mod:1;    /* assert or disassert */
   14.11 -   uint8_t   reserved:2;
   14.12 -   uint8_t   vector;
   14.13 -};
   14.14 -
   14.15  typedef struct {
   14.16      /* interrupt for PIC and ext type IOAPIC interrupt */
   14.17      uint64_t   vl_ext_intr[VLAPIC_INT_COUNT];
   14.18 @@ -51,7 +43,6 @@ typedef struct {
   14.19      uint32_t   vl_arb_id;
   14.20      uint32_t   vl_state;
   14.21      uint32_t   apic_msg_count;
   14.22 -    struct vapic_bus_message  vl_apic_msg[24];
   14.23  } vlapic_info;
   14.24  
   14.25  #endif /* _VMX_VLAPIC_H_ */
    15.1 --- a/xen/include/public/io/vmx_vpic.h	Sat Nov 05 11:23:02 2005 +0100
    15.2 +++ b/xen/include/public/io/vmx_vpic.h	Sat Nov 05 11:26:29 2005 +0100
    15.3 @@ -77,6 +77,7 @@ uint32_t pic_intack_read(struct vmx_virp
    15.4  void register_pic_io_hook (void);
    15.5  int cpu_get_pic_interrupt(struct vcpu *v, int *type);
    15.6  int is_pit_irq(struct vcpu *v, int irq, int type);
    15.7 +int is_irq_enabled(struct vcpu *v, int irq);
    15.8  void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
    15.9  void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);
   15.10