| 
     
  diff
  -rupN a/tools/libxc/Makefile b/tools/libxc/Makefile 
  ---
  a/tools/libxc/Makefile            2010-04-13
  10:49:37.573793000 -0400 
  +++
  b/tools/libxc/Makefile         2010-04-14
  17:49:26.952638000 -0400 
  @@
  -17,6 +17,7 @@ CTRL_SRCS-y       +=
  xc_physdev.c 
   CTRL_SRCS-y      
  += xc_private.c 
   CTRL_SRCS-y      
  += xc_sedf.c 
   CTRL_SRCS-y      
  += xc_csched.c 
  +CTRL_SRCS-y      
  += xc_arinc653.c 
   CTRL_SRCS-y      
  += xc_tbuf.c 
   CTRL_SRCS-y      
  += xc_pm.c 
   CTRL_SRCS-y      
  += xc_cpu_hotplug.c 
  diff
  -rupN a/tools/libxc/xc_arinc653.c b/tools/libxc/xc_arinc653.c 
  ---
  a/tools/libxc/xc_arinc653.c     1969-12-31 19:00:00.000000000
  -0500 
  +++
  b/tools/libxc/xc_arinc653.c 2010-04-14 17:49:26.952638000 -0400 
  @@ -0,0
  +1,28 @@ 
  +/**************************************************************************** 
  + * (C)
  2010 - DornerWorks, Ltd <DornerWorks.com> 
  +
  **************************************************************************** 
  + * 
  +
  *        File: xc_arinc653.c 
  +
  *      Author: Josh Holtrop <DornerWorks.com> 
  + * 
  + *
  Description: XC Interface to the ARINC 653 scheduler 
  + * 
  + */ 
  + 
  +#include
  "xc_private.h" 
  + 
  +int 
  +xc_sched_arinc653_sched_set( 
  +   
  int xc_handle, 
  +   
  xen_domctl_sched_arinc653_schedule_t * sched) 
  +{ 
  +   
  DECLARE_DOMCTL; 
  + 
  +   
  domctl.cmd = XEN_DOMCTL_scheduler_op; 
  +   
  domctl.domain = (domid_t) 0; 
  +   
  domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_ARINC653; 
  +   
  domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_put_global_info; 
  +   
  set_xen_guest_handle(domctl.u.scheduler_op.u.arinc653.schedule, sched); 
  + 
  +   
  return do_domctl(xc_handle, &domctl); 
  +} 
  diff
  -rupN a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h 
  ---
  a/tools/libxc/xenctrl.h            2010-04-13
  10:49:37.573793000 -0400 
  +++
  b/tools/libxc/xenctrl.h         2010-04-14
  17:49:26.952638000 -0400 
  @@
  -476,6 +476,16 @@ int xc_sched_credit_domain_get(int xc_ha 
                                 
  struct xen_domctl_sched_credit *sdom); 
    
   /** 
  + *
  This function sets the global ARINC 653 schedule. 
  + * 
  + *
  @parm xc_handle a handle to an open hypervisor interface 
  + *
  @parm sched a pointer to the new ARINC 653 schedule 
  + *
  return 0 on success 
  + */ 
  +int
  xc_sched_arinc653_sched_set(int xc_handle, 
  +                               
  xen_domctl_sched_arinc653_schedule_t * sched); 
  + 
  +/** 
   
  * This function sends a trigger to a domain. 
   
  * 
   
  * @parm xc_handle a handle to an open hypervisor interface 
  diff
  -rupN a/xen/common/Makefile b/xen/common/Makefile 
  ---
  a/xen/common/Makefile         2010-04-13
  10:49:37.573793000 -0400 
  +++
  b/xen/common/Makefile     2010-04-13 13:00:31.651749000
  -0400 
  @@
  -14,6 +14,7 @@ obj-y += page_alloc.o 
   obj-y
  += rangeset.o 
   obj-y
  += sched_credit.o 
   obj-y
  += sched_sedf.o 
  +obj-y
  += sched_arinc653.o 
   obj-y
  += schedule.o 
   obj-y
  += shutdown.o 
   obj-y
  += softirq.o 
  diff
  -rupN a/xen/common/sched_arinc653.c b/xen/common/sched_arinc653.c 
  ---
  a/xen/common/sched_arinc653.c       1969-12-31
  19:00:00.000000000 -0500 
  +++
  b/xen/common/sched_arinc653.c    2010-04-14 18:13:26.163404000
  -0400 
  @@ -0,0
  +1,590 @@ 
  +/* 
  + *
  File: sched_arinc653.c 
  + *
  Copyright (c) 2010, DornerWorks, Ltd. <DornerWorks.com> 
  + * 
  + *
  Description: 
  +
  *   This file provides an ARINC653-compatible scheduling algorithm 
  +
  *   for use in Xen. 
  + * 
  + *
  This program is free software; you can redistribute it and/or modify it 
  + *
  under the terms of the GNU General Public License as published by the Free 
  + *
  software Foundation; either version 2 of the License, or (at your option) 
  + * any
  later version. 
  + * 
  + *
  This program is distributed in the hope that it will be useful, 
  + * but
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  + *
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
  + * See
  the GNU General Public License for more details. 
  + */ 
  + 
  + 
  +/************************************************************************** 
  + *
  Includes                                                              
  * 
  +
  *************************************************************************/ 
  +#include
  <xen/lib.h> 
  +#include
  <xen/sched.h> 
  +#include
  <xen/sched-if.h> 
  +#include
  <xen/timer.h> 
  +#include
  <xen/softirq.h> 
  +#include
  <xen/time.h> 
  +#include
  <xen/errno.h> 
  +#include
  <xen/list.h> 
  +#include
  <public/domctl.h>         
  /* ARINC653_MAX_DOMAINS_PER_SCHEDULE */ 
  +#include
  <xen/guest_access.h> 
  + 
  + 
  +/************************************************************************** 
  + *
  Private
  Macros                                                        
  * 
  +
  **************************************************************************/ 
  + 
  +/** 
  + *
  Retrieve the idle VCPU for a given physical CPU 
  + */ 
  +#define
  IDLETASK(cpu)  ((struct vcpu *) per_cpu(schedule_data, (cpu)).idle) 
  + 
  +/** 
  + *
  Return a pointer to the ARINC 653-specific scheduler data information 
  + *
  associated with the given VCPU (vc) 
  + */ 
  +#define
  AVCPU(vc) ((arinc653_vcpu_t *)(vc)->sched_priv) 
  + 
  +/************************************************************************** 
  + *
  Private Type
  Definitions                                              
  * 
  +
  **************************************************************************/ 
  + 
  +/** 
  + * The
  sched_entry_t structure holds a single entry of the 
  + *
  ARINC 653 schedule. 
  + */ 
  +typedef
  struct sched_entry_s 
  +{ 
  +   
  /* dom_handle holds the handle ("UUID") for the domain that this 
  +    
  * schedule entry refers to. */ 
  +   
  xen_domain_handle_t dom_handle; 
  +   
  /* vcpu_id holds the VCPU number for the VCPU that this schedule 
  +    
  * entry refers to. */ 
  +   
  int                
  vcpu_id; 
  +   
  /* runtime holds the number of nanoseconds that the VCPU for this 
  +    
  * schedule entry should be allowed to run per major frame. */ 
  +   
  s_time_t           
  runtime; 
  +   
  /* vc holds a pointer to the Xen VCPU structure */ 
  +   
  struct vcpu *       vc; 
  +}
  sched_entry_t; 
  + 
  +/** 
  + * The
  arinc653_vcpu_t structure holds ARINC 653-scheduler-specific 
  + *
  information for all non-idle VCPUs 
  + */ 
  +typedef
  struct arinc653_vcpu_s 
  +{ 
  +   
  /* vc points to Xen's struct vcpu so we can get to it from an 
  +    
  * arinc653_vcpu_t pointer. */ 
  +   
  struct vcpu *       vc; 
  +   
  /* awake holds whether the VCPU has been woken with vcpu_wake() */ 
  +   
  bool_t             
  awake; 
  +   
  /* list holds the linked list information for the list this VCPU 
  +    
  * is stored in */ 
  +   
  struct list_head    list; 
  +}
  arinc653_vcpu_t; 
  + 
  + 
  +/************************************************************************** 
  + *
  Global
  Data                                
                             * 
  +
  **************************************************************************/ 
  + 
  +/** 
  + *
  This array holds the active ARINC 653 schedule. 
  + * 
  + *
  When the system tries to start a new VCPU, this schedule is scanned 
  + * to
  look for a matching (handle, VCPU #) pair. If both the handle
  ("UUID") 
  + * and
  VCPU number match, then the VCPU is allowed to run. Its run time 
  + *
  (per major frame) is given in the third entry of the schedule. 
  + */ 
  +static
  sched_entry_t arinc653_schedule[ARINC653_MAX_DOMAINS_PER_SCHEDULE] = { 
  +   
  { "", 0, MILLISECS(10), NULL } 
  +}; 
  + 
  +/** 
  + *
  This variable holds the number of entries that are valid in 
  + * the
  arinc653_schedule table. 
  + * 
  + *
  This is not necessarily the same as the number of domains in the 
  + *
  schedule. A domain could be listed multiple times within the schedule, 
  + * or
  a domain with multiple VCPUs could have a different 
  + *
  schedule entry for each VCPU. 
  + * 
  + * A
  value of 1 means that only 1 domain (Dom0) will initially be started. 
  + */ 
  +static
  int num_schedule_entries = 1; 
  + 
  +/** 
  + *
  arinc653_major_frame holds the major frame time for the ARINC 653 schedule. 
  + */ 
  +static
  s_time_t arinc653_major_frame = MILLISECS(10); 
  + 
  +/** 
  + *
  next_major_frame holds the time that the next major frame starts 
  + */ 
  +static
  s_time_t next_major_frame = 0; 
  + 
  +/** 
  + *
  vcpu_list holds pointers to all Xen VCPU structures for iterating through 
  + */ 
  +static
  LIST_HEAD(vcpu_list); 
  + 
  +/************************************************************************** 
  + *
  Scheduler
  functions                                                   
  * 
  +
  **************************************************************************/ 
  + 
  +/** 
  + *
  This function compares two domain handles. 
  + * 
  + *
  @param h1        Pointer to handle 1 
  + *
  @param h2        Pointer to handle 2 
  + * 
  + *
  @return          <ul> 
  +
  *                 
  <li> <0:  handle 1 is less than handle 2 
  +
  *                 
  <li>  0:  handle 1 is equal to handle 2 
  +
  *                 
  <li> >0:  handle 1 is greater than handle 2 
  +
  *                 
  </ul> 
  + */ 
  +static
  int dom_handle_cmp(const xen_domain_handle_t h1, 
  +                         
  const xen_domain_handle_t h2) 
  +{ 
  +   
  return memcmp(h1, h2, sizeof(xen_domain_handle_t)); 
  +} /*
  end dom_handle_cmp */ 
  + 
  +/** 
  + *
  This function searches the vcpu list to find a VCPU that matches 
  + * the
  domain handle and VCPU ID specified. 
  + * 
  + *
  @param handle    Pointer to handler 
  + *
  @param vcpu_id   VCPU ID 
  + * 
  + *
  @return          <ul> 
  +
  *                 
  <li> Pointer to the matching VCPU if one is found 
  +
  *                 
  <li> NULL otherwise 
  +
  *                 
  </ul> 
  + */ 
  +static
  struct vcpu * find_vcpu(xen_domain_handle_t handle, int vcpu_id) 
  +{ 
  +   
  arinc653_vcpu_t * avcpu; /* loop index variable */ 
  +   
  struct vcpu * vc = NULL; 
  + 
  +   
  /* loop through the vcpu_list looking for the specified VCPU */ 
  +   
  list_for_each_entry(avcpu, &vcpu_list, list) 
  +   
  { 
  +       
  /* If the handles & VCPU IDs match, we've found a matching VCPU */ 
  +       
  if ((dom_handle_cmp(avcpu->vc->domain->handle, handle) == 0) 
  +            
  && (vcpu_id == avcpu->vc->vcpu_id)) 
  +       
  { 
  +           
  vc = avcpu->vc; 
  +           
  /* 
  +            
  * "break" statement used instead of loop control variable because 
  +            
  * the macro used for this loop does not support using loop control 
  +            
  * variables 
  +            
  */ 
  +           
  break; 
  +       
  } 
  +   
  } 
  + 
  +   
  return vc; 
  +} /*
  end find_vcpu */ 
  + 
  +/** 
  + *
  This function updates the pointer to the Xen VCPU structure for each entry in 
  + * the
  ARINC 653 schedule. 
  + * 
  + *
  @param          
  <None> 
  + *
  @return          <None> 
  + */ 
  +static
  void update_schedule_vcpus(void) 
  +{ 
  +   
  /* Loop through the number of entries in the schedule */ 
  +   
  for (int i = 0; i < num_schedule_entries; i++) 
  +   
  { 
  +       
  /* Update the pointer to the Xen VCPU structure for the current entry */ 
  +       
  arinc653_schedule[i].vc = 
  +           
  find_vcpu(arinc653_schedule[i].dom_handle, 
  +                     
  arinc653_schedule[i].vcpu_id); 
  +   
  } 
  +} /*
  end update_schedule_vcpus */ 
  + 
  +/** 
  + *
  This function is called by the arinc653_adjust_global scheduler 
  + *
  callback function in response to a domain control hypercall with 
  + * a
  scheduler operation. 
  + * 
  + * The
  parameter schedule is set to be the address of a local variable from 
  + *
  within arinc653_adjust_global(), so it is guaranteed to not be NULL. 
  + * 
  + *
  @param schedule  Pointer to the new ARINC 653 schedule. 
  + * 
  + *
  @return          <ul> 
  +
  *                  <li>
  0 = success 
  +
  *                 
  <li> !0 = error 
  +
  *                 
  </ul> 
  + */ 
  +static
  int arinc653_sched_set(xen_domctl_sched_arinc653_schedule_t * schedule) 
  +{ 
  +   
  int ret = 0; 
  +   
  s_time_t total_runtime = 0; 
  +   
  bool_t found_dom0 = 0; 
  +   
  const static xen_domain_handle_t dom0_handle = {0}; 
  + 
  +   
  /* check for valid major frame and number of schedule entries */ 
  +   
  if ( (schedule->major_frame <= 0) 
  +     
  || (schedule->num_sched_entries < 1) 
  +     
  || (schedule->num_sched_entries > ARINC653_MAX_DOMAINS_PER_SCHEDULE) ) 
  +   
  { 
  +       
  ret = -EINVAL; 
  +   
  } 
  + 
  +   
  if (ret == 0) 
  +   
  { 
  +       
  for (int i = 0; i < schedule->num_sched_entries; i++) 
  +       
  { 
  +           
  /* 
  +            
  * look for domain 0 handle - every schedule must contain 
  +            
  * some time for domain 0 to run 
  +            
  */ 
  +           
  if (dom_handle_cmp(schedule->sched_entries[i].dom_handle, 
  +                              
  dom0_handle) == 0) 
  +           
  { 
  +               
  found_dom0 = 1; 
  +           
  } 
  + 
  +           
  /* check for a valid VCPU ID and run time */ 
  +           
  if ( (schedule->sched_entries[i].vcpu_id < 0) 
  +             
  || (schedule->sched_entries[i].runtime <= 0) ) 
  +          
   { 
  +               
  ret = -EINVAL; 
  +           
  } 
  +           
  else 
  +           
  { 
  +               
  /* Add this entry's run time to total run time */ 
  +               
  total_runtime += schedule->sched_entries[i].runtime; 
  +           
  } 
  +       
  } /* end loop through schedule entries */ 
  +   
  } 
  + 
  +   
  if (ret == 0) 
  +   
  { 
  +       
  /* error if the schedule doesn't contain a slot for domain 0 */ 
  +       
  if (found_dom0 == 0) 
  +       
  { 
  +           
  ret = -EINVAL; 
  +       
  } 
  +   
  } 
  + 
  +   
  if (ret == 0) 
  +   
  { 
  +       
  /* 
  +        
  * error if the major frame is not large enough to run all entries 
  +        
  * as indicated by comparing the total run time to the major frame 
  +        
  * length 
  +        
  */ 
  +       
  if (total_runtime > schedule->major_frame) 
  +      
   { 
  +           
  ret = -EINVAL; 
  +       
  } 
  +   
  } 
  + 
  +   
  if (ret == 0) 
  +   
  { 
  +       
  /* copy the new schedule into place */ 
  +       
  num_schedule_entries = schedule->num_sched_entries; 
  +       
  arinc653_major_frame = schedule->major_frame; 
  +       
  for (int i = 0; i < num_schedule_entries; i++) 
  +       
  { 
  +           
  memcpy(arinc653_schedule[i].dom_handle, 
  +                  
  schedule->sched_entries[i].dom_handle, 
  +                  
  sizeof(arinc653_schedule[i].dom_handle)); 
  +           
  arinc653_schedule[i].vcpu_id = schedule->sched_entries[i].vcpu_id; 
  +           
  arinc653_schedule[i].runtime = schedule->sched_entries[i].runtime; 
  +       
  } 
  +       
  update_schedule_vcpus(); 
  + 
  +       
  /* 
  +        
  * The newly-installed schedule takes effect immediately. 
  +        
  * We do not even wait for the current major frame to expire. 
  +        
  * 
  +        
  * Signal a new major frame to begin. The next major frame 
  +        
  * is set up by the do_schedule callback function when it 
  +      
    * is next invoked. 
  +        
  */ 
  +       
  next_major_frame = NOW(); 
  +   
  } 
  + 
  +   
  return ret; 
  +} /*
  end arinc653_sched_set */ 
  + 
  +/** 
  + * Xen
  scheduler callback function to adjust global scheduling parameters 
  + * 
  + *
  @param op    Pointer to the domain control scheduler operation
  structure 
  + * 
  + *
  @return          <ul> 
  +
  *                 
  <li> 0 for success 
  +
  *                 
  <li> !0 if there is an error 
  +
  *                 
  </ul> 
  + */ 
  +static
  int arinc653_adjust_global(struct xen_domctl_scheduler_op * op) 
  +{ 
  +   
  int ret = -1; 
  +   
  xen_domctl_sched_arinc653_schedule_t new_sched; 
  + 
  +   
  if (op->cmd == XEN_DOMCTL_SCHEDOP_put_global_info) 
  +   
  { 
  +       
  if (copy_from_guest(&new_sched, op->u.arinc653.schedule, 1) != 0) 
  +       
  { 
  +           
  ret = -EFAULT; 
  +       
  } 
  +       
  else 
  +       
  { 
  +           
  ret = arinc653_sched_set(&new_sched); 
  +       
  } 
  +   
  } 
  + 
  +   
  return ret; 
  +} /*
  end arinc653_adjust_global */ 
  + 
  +/** 
  + * Xen
  scheduler callback function to initialize a virtual CPU (VCPU). 
  + * 
  + *
  @param v         Pointer to the VCPU
  structure 
  + * 
  + *
  @return          <ul> 
  +
  *                 
  <li> 0 if the VCPU is allowed to run 
  +
  *                 
  <li> !0 if there is an error 
  +
  *                 
  </ul> 
  + */ 
  +static
  int arinc653_init_vcpu(struct vcpu * v) 
  +{ 
  +   
  int ret = -1; 
  + 
  +   
  if (is_idle_vcpu(v)) 
  +   
  { 
  +       
  /* 
  +        
  * The idle VCPU is created by Xen to run when no domains 
  +        
  * are runnable or require CPU time. 
  +        
  * It is similar to an "idle task" or "halt loop" process 
  +        
  * in an operating system. 
  +        
  * We do not track any scheduler information for the idle VCPU. 
  +        
  */ 
  +       
  v->sched_priv = NULL; 
  +       
  ret = 0; 
  +   
  } 
  +   
  else 
  +   
  { 
  +       
  /* 
  +        
  * Allocate memory for the ARINC 653-specific scheduler data information 
  +        
  * associated with the given VCPU (vc). 
  +        
  */ 
  +       
  v->sched_priv = xmalloc(arinc653_vcpu_t); 
  +       
  if (AVCPU(v) != NULL) 
  +    
     { 
  +           
  /* 
  +            
  * Initialize our ARINC 653 scheduler-specific information 
  +            
  * for the VCPU. 
  +            
  * The VCPU starts "asleep." 
  +            
  * When Xen is ready for the VCPU to run, it will call 
  +            
  * the vcpu_wake scheduler callback function and our 
  +            
  * scheduler will mark the VCPU awake. 
  +            
  */ 
  +           
  AVCPU(v)->vc = v; 
  +           
  AVCPU(v)->awake = 0; 
  +           
  list_add(&AVCPU(v)->list, &vcpu_list); 
  +  
           ret = 0; 
  +           
  update_schedule_vcpus(); 
  +       
  } 
  +   
  } 
  + 
  +   
  return ret; 
  +} /*
  end arinc653_init_vcpu */ 
  + 
  +/** 
  + * Xen
  scheduler callback function to remove a VCPU 
  + * 
  + *
  @param v         Pointer to the VCPU
  structure to remove 
  + * 
  + *
  @return          <None> 
  + */ 
  +static
  void arinc653_destroy_vcpu(struct vcpu * v) 
  +{ 
  +   
  if (AVCPU(v) != NULL) 
  +   
  { 
  +       
  /* remove the VCPU from whichever list it is on */ 
  +       
  list_del(&AVCPU(v)->list); 
  +       
  /* free the arinc653_vcpu structure */ 
  +       
  xfree(AVCPU(v)); 
  +       
  update_schedule_vcpus(); 
  +   
  } 
  +} /*
  end arinc653_destroy_vcpu */ 
  + 
  +/** 
  + * Xen
  scheduler callback function to select a VCPU to run. 
  + *
  This is the main scheduler routine. 
  + * 
  + *
  @param t         Current time 
  + * 
  + *
  @return          Time slice and
  address of the VCPU structure for the chosen 
  +
  *                 
  domain 
  + */ 
  +static
  struct task_slice arinc653_do_schedule(s_time_t t) 
  +{ 
  +   
  struct task_slice ret;                      /*
  hold the chosen domain */ 
  +   
  struct vcpu * new_task = NULL; 
  +   
  static int sched_index = 0; 
  +   
  static s_time_t last_major_frame; 
  +   
  static s_time_t last_switch_time; 
  +   
  static s_time_t next_switch_time; 
  + 
  +   
  if (t >= next_major_frame) 
  +   
  { 
  +       
  /* time to enter a new major frame 
  +        
  * the first time this function is called, this will be true */ 
  +       
  sched_index = 0; 
  +       
  last_major_frame = last_switch_time = t; 
  +       
  next_major_frame = t + arinc653_major_frame; 
  +   
  } 
  +   
  else if (t >= next_switch_time) 
  +   
  { 
  +       
  /* time to switch to the next domain in this major frame */ 
  +       
  sched_index++; 
  +       
  last_switch_time = next_switch_time; 
  +   
  } 
  + 
  + 
    /* 
  +    
  * If there are more domains to run in the current major frame, set 
  +    
  * next_switch_time equal to the last switch time + this domain's run time. 
  +    
  * Otherwise, set next_switch_time equal to the start of the next major 
  +    
  * frame. 
  +   
   */ 
  +   
  next_switch_time = (sched_index < num_schedule_entries) 
  +                    
  ? last_switch_time + arinc653_schedule[sched_index].runtime 
  +                    
  : next_major_frame; 
  + 
  +   
  /* 
  +    
  * If there are more domains to run in the current major frame, set 
  +    
  * new_task equal to the address of next domain's VCPU structure. 
  +    
  * Otherwise, set new_task equal to the address of the idle task's VCPU 
  +    
  * structure. 
  +    
  */ 
  +   
  new_task = (sched_index < num_schedule_entries) 
  +         
           ?
  arinc653_schedule[sched_index].vc 
  +                  
  : IDLETASK(0); 
  + 
  +   
  /* Check to see if the new task can be run (awake & runnable). */ 
  +   
  if (!((new_task != NULL) 
  +           
  && AVCPU(new_task)->awake 
  +           
  && vcpu_runnable(new_task)) ) 
  +   
  { 
  +       
  new_task = IDLETASK(0); 
  +   
  } 
  +   
  BUG_ON(new_task == NULL); 
  + 
  +   
  /* 
  +    
  * Check to make sure we did not miss a major frame. 
  +    
  * This is a good test for robust partitioning. 
  +    
  */ 
  +   
  BUG_ON(t >= next_major_frame); 
  + 
  +   
  /* 
  +    
  * Return the amount of time the next domain has to run and the address 
  +    
  * of the selected task's VCPU structure. 
  +    
  */ 
  +   
  ret.time = next_switch_time - t; 
  +   
  ret.task = new_task; 
  + 
  +   
  BUG_ON(ret.time <= 0); 
  + 
  +   
  return ret; 
  +} /*
  end arinc653_do_schedule */ 
  + 
  +/** 
  + * Xen
  scheduler callback function to select a CPU for the VCPU to run on 
  + * 
  + *
  @param v         Pointer to the VCPU
  structure for the current domain 
  + * 
  + *
  @return          Number of
  selected physical CPU 
  + */ 
  +static
  int arinc653_pick_cpu(struct vcpu * v) 
  +{ 
  +   
  /* this implementation only supports one physical CPU */ 
  +   
  return 0; 
  +} /*
  end arinc653_pick_cpu */ 
  + 
  +/** 
  + * Xen
  scheduler callback function to wake up a VCPU 
  + * 
  + *
  @param vc        Pointer to the VCPU
  structure for the current domain 
  + * 
  + *
  @return          <None> 
  + */ 
  +static
  void arinc653_vcpu_wake(struct vcpu * vc) 
  +{ 
  +   
  /* boolean flag to indicate first run */ 
  +   
  static bool_t dont_raise_softirq = 0; 
  + 
  +   
  if (AVCPU(vc) != NULL)  /* check that this is a VCPU we are tracking */ 
  +   
  { 
  +       
  AVCPU(vc)->awake = 1; 
  +   
  } 
  + 
  +   
  /* the first time the vcpu_wake function is called, we should raise 
  +    
  * a softirq to invoke the do_scheduler callback */ 
  +   
  if (!dont_raise_softirq) 
  +   
  { 
  +       
  cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ); 
  +       
  dont_raise_softirq = 1; 
  +   
  } 
  +} /*
  end arinc653_vcpu_wake */ 
  + 
  +/** 
  + * Xen
  scheduler callback function to sleep a VCPU 
  + * 
  + *
  @param vc        Pointer to the VCPU
  structure for the current domain 
  + * 
  + *
  @return          <None> 
  + */ 
  +static
  void arinc653_vcpu_sleep(struct vcpu * vc) 
  +{ 
  +   
  if (AVCPU(vc) != NULL)  /* check that this is a VCPU we are tracking */ 
  +   
  { 
  +       
  AVCPU(vc)->awake = 0; 
  +   
  } 
  + 
  +   
  /* if the VCPU being put to sleep is the same one that is currently 
  +    
  * running, raise a softirq to invoke the scheduler to switch domains */ 
  +   
  if (per_cpu(schedule_data, vc->processor).curr == vc) 
  +   
  { 
  +       
  cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ); 
  +   
  } 
  +} /*
  end arinc653_vcpu_sleep */ 
  + 
  +/** 
  + *
  This structure defines our scheduler for Xen. 
  + * The
  entries tell Xen where to find our scheduler-specific 
  + *
  callback functions. 
  + * The
  symbol must be visible to the rest of Xen at link time. 
  + */ 
  +struct
  scheduler sched_arinc653_def = { 
  +   
  .name           =
  "ARINC 653 Scheduler", 
  +   
  .opt_name       = "arinc653", 
  +   
  .sched_id       = XEN_SCHEDULER_ARINC653, 
  + 
  +   
  .init_domain    = NULL, 
  +   
  .destroy_domain = NULL, 
  + 
  +   
  .init_vcpu      = arinc653_init_vcpu, 
  +   
  .destroy_vcpu   = arinc653_destroy_vcpu, 
  + 
  +   
  .do_schedule    = arinc653_do_schedule, 
  +   
  .pick_cpu       = arinc653_pick_cpu, 
  +   
  .dump_cpu_state = NULL, 
  +   
  .sleep          =
  arinc653_vcpu_sleep, 
  +   
  .wake           =
  arinc653_vcpu_wake, 
  +   
  .adjust         = NULL, 
  +   
  .adjust_global  = arinc653_adjust_global, 
  +}; 
  diff
  -rupN a/xen/common/schedule.c b/xen/common/schedule.c 
  ---
  a/xen/common/schedule.c     2010-04-14 10:57:11.262796000
  -0400 
  +++
  b/xen/common/schedule.c  2010-04-14 16:40:21.543608000 -0400 
  @@ -7,7
  +7,8 @@ 
   
  *        File: common/schedule.c 
   
  *      Author: Rolf Neugebauer & Keir Fraser 
   
  *             
  Updated for generic API by Mark Williamson 
  - *  
  +
  *             
  ARINC653 scheduler added by DornerWorks <DornerWorks.com> 
  + * 
   
  * Description: Generic CPU scheduling code 
   
  *             
  implements support functionality for the Xen scheduler API. 
   
  * 
  @@
  -56,9 +57,11 @@ DEFINE_PER_CPU(struct schedule_data, sch 
    
   extern
  const struct scheduler sched_sedf_def; 
   extern
  const struct scheduler sched_credit_def; 
  +extern
  const struct scheduler sched_arinc653_def; 
   static
  const struct scheduler *__initdata schedulers[] = { 
    
    &sched_sedf_def, 
      
  &sched_credit_def, 
  +   
  &sched_arinc653_def, 
      
  NULL 
   }; 
    
  diff
  -rupN a/xen/include/public/domctl.h b/xen/include/public/domctl.h 
  ---
  a/xen/include/public/domctl.h 2010-04-14 10:57:11.262796000 -0400 
  +++
  b/xen/include/public/domctl.h         2010-04-14
  16:40:21.543608000 -0400 
  @@
  -23,6 +23,8 @@ 
   
  * 
   
  * Copyright (c) 2002-2003, B Dragovic 
   
  * Copyright (c) 2002-2006, K Fraser 
  + * 
  + *
  ARINC653 Scheduler type added by DornerWorks <DornerWorks.com>. 
   
  */ 
    
   #ifndef
  __XEN_PUBLIC_DOMCTL_H__ 
  @@
  -303,11 +305,43 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_v 
   /*
  Scheduler types. */ 
   #define
  XEN_SCHEDULER_SEDF     4 
   #define
  XEN_SCHEDULER_CREDIT   5 
  +#define
  XEN_SCHEDULER_ARINC653 6 
  + 
   /*
  Set or get info? */ 
   #define
  XEN_DOMCTL_SCHEDOP_putinfo 0 
   #define
  XEN_DOMCTL_SCHEDOP_getinfo 1 
   #define
  XEN_DOMCTL_SCHEDOP_put_global_info 2 
   #define
  XEN_DOMCTL_SCHEDOP_get_global_info 3 
  + 
  +/* 
  + *
  This structure is used to pass a new ARINC653 schedule from a 
  + *
  privileged domain (ie dom0) to Xen. 
  + */ 
  +#define
  ARINC653_MAX_DOMAINS_PER_SCHEDULE   64 
  +struct
  xen_domctl_sched_arinc653_schedule { 
  +   
  /* major_frame holds the time for the new schedule's major frame 
  +    
  * in nanoseconds. */ 
  +   
  int64_t     major_frame; 
  +   
  /* num_sched_entries holds how many of the entries in the 
  +    
  * sched_entries[] array are valid. */ 
  +   
  uint8_t     num_sched_entries; 
  +   
  /* The sched_entries array holds the actual schedule entries. */ 
  +   
  struct { 
  +       
  /* dom_handle must match a domain's UUID */ 
  +       
  xen_domain_handle_t dom_handle; 
  +       
  /* If a domain has multiple VCPUs, vcpu_id specifies which one 
  +        
  * this schedule entry applies to. It should be set to 0 if 
  +        
  * there is only one VCPU for the domain. */ 
  +       
  int                 vcpu_id; 
  +       
  /* runtime specifies the amount of time that should be allocated 
  +        
  * to this VCPU per major frame. It is specified in nanoseconds */ 
  +       
  int64_t            
  runtime; 
  +   
  } sched_entries[ARINC653_MAX_DOMAINS_PER_SCHEDULE]; 
  +}; 
  +typedef
  struct xen_domctl_sched_arinc653_schedule 
  +   
  xen_domctl_sched_arinc653_schedule_t; 
  +DEFINE_XEN_GUEST_HANDLE(xen_domctl_sched_arinc653_schedule_t); 
  + 
   struct
  xen_domctl_scheduler_op { 
      
  uint32_t sched_id;  /* XEN_SCHEDULER_* */ 
     
   uint32_t cmd;       /*
  XEN_DOMCTL_SCHEDOP_* */ 
  @@
  -323,6 +357,9 @@ struct xen_domctl_scheduler_op { 
              
  uint16_t weight; 
              
  uint16_t cap; 
          
  } credit; 
  +       
  struct xen_domctl_sched_arinc653 { 
  +           
  XEN_GUEST_HANDLE(xen_domctl_sched_arinc653_schedule_t) schedule; 
  +       
  } arinc653; 
      
  } u; 
   }; 
   typedef
  struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t; 
   |