[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Add Xenoprof passive domain support



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 23591d2c46aa666a9d50cf36baf73aa0b95aa11b
# Parent  b12cd185d579a0fb3b74b73e44add5524304d8cc
Add Xenoprof passive domain support
Signed-off-by: Yang Xiaowei <xiaowei.yang@xxxxxxxxx>
Signed-off-by: Jose Renato Santos <jsantos@xxxxxxxxxx>
---
 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c |  134 +++++++
 patches/linux-2.6.16.13/xenoprof-generic.patch     |   81 ++--
 xen/arch/x86/oprofile/nmi_int.c                    |    2 
 xen/arch/x86/oprofile/xenoprof.c                   |  358 +++++++++++++--------
 xen/include/public/xenoprof.h                      |    9 
 xen/include/xen/xenoprof.h                         |    1 
 6 files changed, 404 insertions(+), 181 deletions(-)

diff -r b12cd185d579 -r 23591d2c46aa 
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c
--- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c        Tue Jun 27 
11:17:14 2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c        Tue Jun 27 
11:23:06 2006 +0100
@@ -28,6 +28,7 @@
 
 #include <xen/interface/xen.h>
 #include <xen/interface/xenoprof.h>
+#include <../../../drivers/oprofile/cpu_buffer.h>
 
 static int xenoprof_start(void);
 static void xenoprof_stop(void);
@@ -50,6 +51,11 @@ int ovf_irq[NR_CPUS];
 /* cpu model type string - copied from Xen memory space on XENOPROF_init 
command */
 char cpu_type[XENOPROF_CPU_TYPE_SIZE];
 
+/* Passive sample buffers shared with Xen */
+xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS];
+/* Passive shared buffer area */
+char *p_shared_buffer[MAX_OPROF_DOMAINS];
+
 #ifdef CONFIG_PM
 
 static int xenoprof_suspend(struct sys_device * dev, pm_message_t state)
@@ -102,16 +108,14 @@ static void __exit exit_driverfs(void)
 #endif /* CONFIG_PM */
 
 unsigned long long oprofile_samples = 0;
-
-static irqreturn_t 
-xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+unsigned long long p_oprofile_samples = 0;
+
+unsigned int pdomains;
+struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
+
+static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
 {
        int head, tail, size;
-       struct xenoprof_buf * buf;
-       int cpu;
-
-       cpu = smp_processor_id();
-       buf = xenoprof_buf[cpu];
 
        head = buf->event_head;
        tail = buf->event_tail;
@@ -122,7 +126,10 @@ xenoprof_ovf_interrupt(int irq, void * d
                        oprofile_add_pc(buf->event_log[tail].eip,
                                        buf->event_log[tail].mode,
                                        buf->event_log[tail].event);
-                       oprofile_samples++;
+                       if (!is_passive)
+                               oprofile_samples++;
+                       else
+                               p_oprofile_samples++;
                        tail++;
                }
                tail = 0;
@@ -131,11 +138,47 @@ xenoprof_ovf_interrupt(int irq, void * d
                oprofile_add_pc(buf->event_log[tail].eip,
                                buf->event_log[tail].mode,
                                buf->event_log[tail].event);
-               oprofile_samples++;
+               if (!is_passive)
+                       oprofile_samples++;
+               else
+                       p_oprofile_samples++;
                tail++;
        }
 
        buf->event_tail = tail;
+}
+
+static void xenoprof_handle_passive(void)
+{
+       int i, j;
+
+       for (i = 0; i < pdomains; i++)
+               for (j = 0; j < passive_domains[i].nbuf; j++) {
+                       xenoprof_buf_t *buf = p_xenoprof_buf[i][j];
+                       if (buf->event_head == buf->event_tail)
+                               continue;
+                        oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_START, 
passive_domains[i].domain_id);
+                       xenoprof_add_pc(buf, 1);
+                        oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_STOP, 
passive_domains[i].domain_id);
+               }                       
+}
+
+static irqreturn_t 
+xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+       struct xenoprof_buf * buf;
+       int cpu;
+       static unsigned long flag;
+
+       cpu = smp_processor_id();
+       buf = xenoprof_buf[cpu];
+
+       xenoprof_add_pc(buf, 0);
+
+       if (is_primary && !test_and_set_bit(0, &flag)) {
+               xenoprof_handle_passive();
+               clear_bit(0, &flag);
+       }
 
        return IRQ_HANDLED;
 }
@@ -312,6 +355,63 @@ out:
        return ret;
 }
 
+static int xenoprof_set_passive(int * p_domains,
+                                unsigned int pdoms)
+{
+       int ret;
+       int i, j;
+       int vm_size;
+       int npages;
+       struct xenoprof_buf *buf;
+       pgprot_t prot = __pgprot(_KERNPG_TABLE);
+
+       if (!is_primary)
+               return 0;
+
+       if (pdoms > MAX_OPROF_DOMAINS)
+               return -E2BIG;
+
+       ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < pdoms; i++) {
+               passive_domains[i].domain_id = p_domains[i];
+               passive_domains[i].max_samples = 2048;
+               ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive, 
&passive_domains[i]);
+               if (ret)
+                       return ret;
+
+               npages = (passive_domains[i].bufsize * passive_domains[i].nbuf 
- 1) / PAGE_SIZE + 1;
+               vm_size = npages * PAGE_SIZE;
+
+               p_shared_buffer[i] = (char 
*)vm_map_xen_pages(passive_domains[i].buf_maddr,
+                                                             vm_size, prot);
+               if (!p_shared_buffer[i]) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               for (j = 0; j < passive_domains[i].nbuf; j++) {
+                       buf = (struct xenoprof_buf *)
+                               &p_shared_buffer[i][j * 
passive_domains[i].bufsize];
+                       BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
+                       p_xenoprof_buf[i][buf->vcpu_id] = buf;
+               }
+
+       }
+
+       pdomains = pdoms;
+       return 0;
+
+out:
+       for (j = 0; j < i; j++) {
+               vunmap(p_shared_buffer[j]);
+               p_shared_buffer[j] = NULL;
+       }
+
+       return ret;
+}
 
 struct op_counter_config counter_config[OP_MAX_COUNTER];
 
@@ -346,6 +446,7 @@ struct oprofile_operations xenoprof_ops 
 struct oprofile_operations xenoprof_ops = {
        .create_files   = xenoprof_create_files,
        .set_active     = xenoprof_set_active,
+       .set_passive    = xenoprof_set_passive,
        .setup          = xenoprof_setup,
        .shutdown       = xenoprof_shutdown,
        .start          = xenoprof_start,
@@ -420,6 +521,8 @@ int __init oprofile_arch_init(struct opr
 
 void __exit oprofile_arch_exit(void)
 {
+       int i;
+
        if (using_xenoprof)
                exit_driverfs();
 
@@ -427,6 +530,13 @@ void __exit oprofile_arch_exit(void)
                vunmap(shared_buffer);
                shared_buffer = NULL;
        }
-       if (is_primary)
+       if (is_primary) {
+               for (i = 0; i < pdomains; i++)
+                       if (p_shared_buffer[i]) {
+                               vunmap(p_shared_buffer[i]);
+                               p_shared_buffer[i] = NULL;
+                       }
                HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL);
-}
+        }
+
+}
diff -r b12cd185d579 -r 23591d2c46aa 
patches/linux-2.6.16.13/xenoprof-generic.patch
--- a/patches/linux-2.6.16.13/xenoprof-generic.patch    Tue Jun 27 11:17:14 
2006 +0100
+++ b/patches/linux-2.6.16.13/xenoprof-generic.patch    Tue Jun 27 11:23:06 
2006 +0100
@@ -1,6 +1,6 @@ diff -pruN ../pristine-linux-2.6.16.13/d
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 
./drivers/oprofile/buffer_sync.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 2006-05-02 
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/buffer_sync.c   2006-05-04 17:41:51.000000000 +0100
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 
./drivers/oprofile/buffer_sync.c
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 2006-05-03 
05:38:44.000000000 +0800
++++ ./drivers/oprofile/buffer_sync.c   2006-06-27 12:14:53.000000000 +0800
 @@ -6,6 +6,10 @@
   *
   * @author John Levon <levon@xxxxxxxxxxxxxxxxx>
@@ -12,7 +12,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
   * This is the core of the buffer management. Each
   * CPU buffer is processed and entered into the
   * global event buffer. Such processing is necessary
-@@ -275,15 +279,24 @@ static void add_cpu_switch(int i)
+@@ -275,15 +279,30 @@ static void add_cpu_switch(int i)
        last_cookie = INVALID_COOKIE;
  }
  
@@ -33,7 +33,13 @@ diff -pruN ../pristine-linux-2.6.16.13/d
 +              break;
 +      case CPU_MODE_XEN:
 +              add_event_entry(XEN_ENTER_SWITCH_CODE);
-+              break;
++              break;
++        case CPU_MODE_PASSIVE_START:
++                add_event_entry(PASSIVE_START_CODE);
++                break;
++        case CPU_MODE_PASSIVE_STOP:
++                add_event_entry(PASSIVE_STOP_CODE);
++                break;
 +      default:
 +              break;
 +      }
@@ -43,7 +49,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
  static void
  add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
  {
-@@ -348,9 +361,9 @@ static int add_us_sample(struct mm_struc
+@@ -348,9 +367,9 @@ static int add_us_sample(struct mm_struc
   * for later lookup from userspace.
   */
  static int
@@ -55,7 +61,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
                add_sample_entry(s->eip, s->event);
                return 1;
        } else if (mm) {
-@@ -496,7 +509,7 @@ void sync_buffer(int cpu)
+@@ -496,10 +515,11 @@ void sync_buffer(int cpu)
        struct mm_struct *mm = NULL;
        struct task_struct * new;
        unsigned long cookie = 0;
@@ -64,34 +70,62 @@ diff -pruN ../pristine-linux-2.6.16.13/d
        unsigned int i;
        sync_buffer_state state = sb_buffer_start;
        unsigned long available;
-@@ -513,12 +526,12 @@ void sync_buffer(int cpu)
++      int domain_switch = NO_DOMAIN_SWITCH;
+ 
+       down(&buffer_sem);
+  
+@@ -513,12 +533,19 @@ void sync_buffer(int cpu)
                struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
   
                if (is_code(s->eip)) {
 -                      if (s->event <= CPU_IS_KERNEL) {
-+                      if (s->event <= CPU_MODE_XEN) {
++                      if (s->event < CPU_TRACE_BEGIN) {
                                /* kernel/userspace switch */
 -                              in_kernel = s->event;
 +                              cpu_mode = s->event;
                                if (state == sb_buffer_start)
                                        state = sb_sample_start;
 -                              add_kernel_ctx_switch(s->event);
-+                              add_cpu_mode_switch(s->event);
++
++                              if (s->event == CPU_MODE_PASSIVE_START)
++                                      domain_switch = 
DOMAIN_SWITCH_START_EVENT1;
++                              else if (s->event == CPU_MODE_PASSIVE_STOP)
++                                      domain_switch = 
DOMAIN_SWITCH_STOP_EVENT1;
++
++                              if (domain_switch != DOMAIN_SWITCH_START_EVENT2)
++                                      add_cpu_mode_switch(s->event);
                        } else if (s->event == CPU_TRACE_BEGIN) {
                                state = sb_bt_start;
                                add_trace_begin();
-@@ -536,7 +549,7 @@ void sync_buffer(int cpu)
+@@ -535,11 +562,20 @@ void sync_buffer(int cpu)
+                               add_user_ctx_switch(new, cookie);
                        }
                } else {
-                       if (state >= sb_bt_start &&
+-                      if (state >= sb_bt_start &&
 -                          !add_sample(mm, s, in_kernel)) {
-+                          !add_sample(mm, s, cpu_mode)) {
-                               if (state == sb_bt_start) {
-                                       state = sb_bt_ignore;
-                                       
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 
./drivers/oprofile/cpu_buffer.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c  2006-05-02 
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/cpu_buffer.c    2006-05-04 17:41:51.000000000 +0100
+-                              if (state == sb_bt_start) {
+-                                      state = sb_bt_ignore;
+-                                      
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
++                      if (domain_switch == DOMAIN_SWITCH_START_EVENT1) {
++                              add_event_entry(s->event);
++                              domain_switch = DOMAIN_SWITCH_START_EVENT2;
++                      } else if (domain_switch == DOMAIN_SWITCH_START_EVENT1) 
{
++                              add_sample_entry(s->eip, s->event);
++                      } else if (domain_switch == DOMAIN_SWITCH_STOP_EVENT1) {
++                              domain_switch = NO_DOMAIN_SWITCH;
++                      } else {
++                              if (state >= sb_bt_start &&
++                                  !add_sample(mm, s, cpu_mode)) {
++                                      if (state == sb_bt_start) {
++                                              state = sb_bt_ignore;
++                                              
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
++                                      }
+                               }
+                       }
+               }
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 
./drivers/oprofile/cpu_buffer.c
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c  2006-05-03 
05:38:44.000000000 +0800
++++ ./drivers/oprofile/cpu_buffer.c    2006-06-19 22:43:53.000000000 +0800
 @@ -6,6 +6,10 @@
   *
   * @author John Levon <levon@xxxxxxxxxxxxxxxxx>
@@ -139,13 +173,12 @@ diff -pruN ../pristine-linux-2.6.16.13/d
  {
        struct task_struct * task;
  
-@@ -181,16 +185,16 @@ static int log_sample(struct oprofile_cp
+@@ -181,16 +185,14 @@ static int log_sample(struct oprofile_cp
                return 0;
        }
  
 -      is_kernel = !!is_kernel;
-+      WARN_ON(cpu_mode > CPU_MODE_XEN);
- 
+-
        task = current;
  
        /* notice a switch from user->kernel or vice versa */
@@ -161,9 +194,9 @@ diff -pruN ../pristine-linux-2.6.16.13/d
        /* notice a task switch */
        if (cpu_buf->last_task != task) {
                cpu_buf->last_task = task;
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h 
./drivers/oprofile/cpu_buffer.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h  2006-05-02 
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/cpu_buffer.h    2006-05-04 17:41:51.000000000 +0100
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h 
./drivers/oprofile/cpu_buffer.h
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h  2006-05-03 
05:38:44.000000000 +0800
++++ ./drivers/oprofile/cpu_buffer.h    2006-06-27 10:38:08.000000000 +0800
 @@ -36,7 +36,7 @@ struct oprofile_cpu_buffer {
        volatile unsigned long tail_pos;
        unsigned long buffer_size;
@@ -173,22 +206,26 @@ diff -pruN ../pristine-linux-2.6.16.13/d
        int tracing;
        struct op_sample * buffer;
        unsigned long sample_received;
-@@ -51,7 +51,9 @@ extern struct oprofile_cpu_buffer cpu_bu
+@@ -51,7 +51,13 @@ extern struct oprofile_cpu_buffer cpu_bu
  void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
  
  /* transient events for the CPU buffer -> event buffer */
 -#define CPU_IS_KERNEL 1
 -#define CPU_TRACE_BEGIN 2
-+#define CPU_MODE_USER    0
-+#define CPU_MODE_KERNEL  1
-+#define CPU_MODE_XEN     2
-+#define CPU_TRACE_BEGIN  3
++#define CPU_MODE_USER           0
++#define CPU_MODE_KERNEL         1
++#define CPU_MODE_XEN            2
++#define CPU_MODE_PASSIVE_START  3
++#define CPU_MODE_PASSIVE_STOP   4
++#define CPU_TRACE_BEGIN         5
++
++#define IGNORED_PC              0
  
  #endif /* OPROFILE_CPU_BUFFER_H */
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h 
./drivers/oprofile/event_buffer.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h        
2006-05-02 22:38:44.000000000 +0100
-+++ ./drivers/oprofile/event_buffer.h  2006-05-04 17:41:51.000000000 +0100
-@@ -29,11 +29,12 @@ void wake_up_buffer_waiter(void);
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h 
./drivers/oprofile/event_buffer.h
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h        
2006-05-03 05:38:44.000000000 +0800
++++ ./drivers/oprofile/event_buffer.h  2006-06-19 22:43:53.000000000 +0800
+@@ -29,11 +29,14 @@ void wake_up_buffer_waiter(void);
  #define CPU_SWITCH_CODE               2
  #define COOKIE_SWITCH_CODE            3
  #define KERNEL_ENTER_SWITCH_CODE      4
@@ -199,12 +236,14 @@ diff -pruN ../pristine-linux-2.6.16.13/d
  #define TRACE_BEGIN_CODE              8
  #define TRACE_END_CODE                        9
 +#define XEN_ENTER_SWITCH_CODE         10
++#define PASSIVE_START_CODE            11
++#define PASSIVE_STOP_CODE             12
   
  #define INVALID_COOKIE ~0UL
  #define NO_COOKIE 0UL
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c 
./drivers/oprofile/oprof.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c       2006-05-02 
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/oprof.c 2006-05-04 17:41:51.000000000 +0100
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c 
./drivers/oprofile/oprof.c
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c       2006-05-03 
05:38:44.000000000 +0800
++++ ./drivers/oprofile/oprof.c 2006-06-19 23:45:17.000000000 +0800
 @@ -5,6 +5,10 @@
   * @remark Read the file COPYING
   *
@@ -225,7 +264,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
  struct oprofile_operations oprofile_ops;
  
  unsigned long oprofile_started;
-@@ -33,6 +37,19 @@ static DECLARE_MUTEX(start_sem);
+@@ -33,6 +37,32 @@ static DECLARE_MUTEX(start_sem);
   */
  static int timer = 0;
  
@@ -242,23 +281,37 @@ diff -pruN ../pristine-linux-2.6.16.13/d
 +      return err;
 +}
 +
++int oprofile_set_passive(int passive_domains[], unsigned int pdomains)
++{
++      int err;
++
++      if (!oprofile_ops.set_passive)
++              return -EINVAL;
++
++      down(&start_sem);
++      err = oprofile_ops.set_passive(passive_domains, pdomains);
++      up(&start_sem);
++      return err;
++}
++
  int oprofile_setup(void)
  {
        int err;
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h 
./drivers/oprofile/oprof.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h       2006-05-02 
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/oprof.h 2006-05-04 17:41:51.000000000 +0100
-@@ -35,5 +35,7 @@ void oprofile_create_files(struct super_
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h 
./drivers/oprofile/oprof.h
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h       2006-05-03 
05:38:44.000000000 +0800
++++ ./drivers/oprofile/oprof.h 2006-06-19 23:42:36.000000000 +0800
+@@ -35,5 +35,8 @@ void oprofile_create_files(struct super_
  void oprofile_timer_init(struct oprofile_operations * ops);
  
  int oprofile_set_backtrace(unsigned long depth);
 +
 +int oprofile_set_active(int active_domains[], unsigned int adomains);
++int oprofile_set_passive(int passive_domains[], unsigned int pdomains);
   
  #endif /* OPROF_H */
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c 
./drivers/oprofile/oprofile_files.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c      
2006-05-02 22:38:44.000000000 +0100
-+++ ./drivers/oprofile/oprofile_files.c        2006-05-04 17:41:51.000000000 
+0100
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c 
./drivers/oprofile/oprofile_files.c
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c      
2006-05-03 05:38:44.000000000 +0800
++++ ./drivers/oprofile/oprofile_files.c        2006-06-19 23:29:07.000000000 
+0800
 @@ -5,15 +5,21 @@
   * @remark Read the file COPYING
   *
@@ -282,7 +335,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
  unsigned long fs_buffer_size = 131072;
  unsigned long fs_cpu_buffer_size = 8192;
  unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
-@@ -117,11 +123,108 @@ static ssize_t dump_write(struct file * 
+@@ -117,11 +123,202 @@ static ssize_t dump_write(struct file * 
  static struct file_operations dump_fops = {
        .write          = dump_write,
  };
@@ -384,17 +437,110 @@ diff -pruN ../pristine-linux-2.6.16.13/d
 +      .write          = adomain_write,
 +};
 +
++static unsigned int pdomains = 0;
++static int passive_domains[MAX_OPROF_DOMAINS];
++static DEFINE_MUTEX(pdom_mutex);
++
++static ssize_t pdomain_write(struct file * file, char const __user * buf, 
++                           size_t count, loff_t * offset)
++{
++      char *tmpbuf;
++      char *startp, *endp;
++      int i;
++      unsigned long val;
++      ssize_t retval = count;
++      
++      if (*offset)
++              return -EINVAL; 
++      if (count > TMPBUFSIZE - 1)
++              return -EINVAL;
++
++      if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++              return -ENOMEM;
++
++      if (copy_from_user(tmpbuf, buf, count)) {
++              kfree(tmpbuf);
++              return -EFAULT;
++      }
++      tmpbuf[count] = 0;
++
++      mutex_lock(&pdom_mutex);
++
++      startp = tmpbuf;
++      /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
++      for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
++              val = simple_strtoul(startp, &endp, 0);
++              if (endp == startp)
++                      break;
++              while (ispunct(*endp) || isspace(*endp))
++                      endp++;
++              passive_domains[i] = val;
++              if (passive_domains[i] != val)
++                      /* Overflow, force error below */
++                      i = MAX_OPROF_DOMAINS + 1;
++              startp = endp;
++      }
++      /* Force error on trailing junk */
++      pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
++
++      kfree(tmpbuf);
++
++      if (pdomains > MAX_OPROF_DOMAINS
++          || oprofile_set_passive(passive_domains, pdomains)) {
++              pdomains = 0;
++              retval = -EINVAL;
++      }
++
++      mutex_unlock(&pdom_mutex);
++      return retval;
++}
++
++static ssize_t pdomain_read(struct file * file, char __user * buf, 
++                          size_t count, loff_t * offset)
++{
++      char * tmpbuf;
++      size_t len;
++      int i;
++      ssize_t retval;
++
++      if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++              return -ENOMEM;
++
++      mutex_lock(&pdom_mutex);
++
++      len = 0;
++      for (i = 0; i < pdomains; i++)
++              len += snprintf(tmpbuf + len,
++                              len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
++                              "%u ", passive_domains[i]);
++      WARN_ON(len > TMPBUFSIZE);
++      if (len != 0 && len <= TMPBUFSIZE)
++              tmpbuf[len-1] = '\n';
++
++      mutex_unlock(&pdom_mutex);
++
++      retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
++
++      kfree(tmpbuf);
++      return retval;
++}
++
++static struct file_operations passive_domain_ops = {
++      .read           = pdomain_read,
++      .write          = pdomain_write,
++};
++
  void oprofile_create_files(struct super_block * sb, struct dentry * root)
  {
        oprofilefs_create_file(sb, root, "enable", &enable_fops);
        oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
 +      oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops);
++      oprofilefs_create_file(sb, root, "passive_domains", 
&passive_domain_ops);
        oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
        oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size);
        oprofilefs_create_ulong(sb, root, "buffer_watershed", 
&fs_buffer_watershed);
-diff -pruN ../pristine-linux-2.6.16.13/include/linux/oprofile.h 
./include/linux/oprofile.h
---- ../pristine-linux-2.6.16.13/include/linux/oprofile.h       2006-05-02 
22:38:44.000000000 +0100
-+++ ./include/linux/oprofile.h 2006-05-04 17:41:51.000000000 +0100
+--- ../pristine-linux-2.6.16.13/include/linux/oprofile.h       2006-05-03 
05:38:44.000000000 +0800
++++ ./include/linux/oprofile.h 2006-06-19 23:52:00.000000000 +0800
 @@ -16,6 +16,8 @@
  #include <linux/types.h>
  #include <linux/spinlock.h>
@@ -404,12 +550,15 @@ diff -pruN ../pristine-linux-2.6.16.13/i
   
  struct super_block;
  struct dentry;
-@@ -27,6 +29,8 @@ struct oprofile_operations {
+@@ -27,6 +29,11 @@ struct oprofile_operations {
        /* create any necessary configuration files in the oprofile fs.
         * Optional. */
        int (*create_files)(struct super_block * sb, struct dentry * root);
 +      /* setup active domains with Xen */
 +      int (*set_active)(int *active_domains, unsigned int adomains);
++        /* setup passive domains with Xen */
++        int (*set_passive)(int *passive_domains, unsigned int pdomains);
++      
        /* Do any necessary interrupt setup. Optional. */
        int (*setup)(void);
        /* Do any necessary interrupt shutdown. Optional. */
diff -r b12cd185d579 -r 23591d2c46aa xen/arch/x86/oprofile/nmi_int.c
--- a/xen/arch/x86/oprofile/nmi_int.c   Tue Jun 27 11:17:14 2006 +0100
+++ b/xen/arch/x86/oprofile/nmi_int.c   Tue Jun 27 11:23:06 2006 +0100
@@ -269,7 +269,7 @@ static int __init p4_init(char * cpu_typ
 { 
        __u8 cpu_model = current_cpu_data.x86_model;
 
-       if (cpu_model > 4)
+       if ((cpu_model > 6) || (cpu_model == 5))
                return 0;
 
 #ifndef CONFIG_SMP
diff -r b12cd185d579 -r 23591d2c46aa xen/arch/x86/oprofile/xenoprof.c
--- a/xen/arch/x86/oprofile/xenoprof.c  Tue Jun 27 11:17:14 2006 +0100
+++ b/xen/arch/x86/oprofile/xenoprof.c  Tue Jun 27 11:23:06 2006 +0100
@@ -13,9 +13,13 @@
 /* Limit amount of pages used for shared buffer (per domain) */
 #define MAX_OPROF_SHARED_PAGES 32
 
-domid_t active_domains[MAX_OPROF_DOMAINS];
+struct domain *active_domains[MAX_OPROF_DOMAINS];
 int active_ready[MAX_OPROF_DOMAINS];
 unsigned int adomains;
+
+struct domain *passive_domains[MAX_OPROF_DOMAINS];
+unsigned int pdomains;
+
 unsigned int activated;
 struct domain *primary_profiler;
 int xenoprof_state = XENOPROF_IDLE;
@@ -25,6 +29,7 @@ u64 corrupted_buffer_samples;
 u64 corrupted_buffer_samples;
 u64 lost_samples;
 u64 active_samples;
+u64 passive_samples;
 u64 idle_samples;
 u64 others_samples;
 
@@ -44,9 +49,15 @@ int is_active(struct domain *d)
     return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_ACTIVE));
 }
 
+int is_passive(struct domain *d)
+{
+    struct xenoprof *x = d->xenoprof;
+    return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_PASSIVE));
+}
+
 int is_profiled(struct domain *d)
 {
-    return is_active(d);
+    return (is_active(d) || is_passive(d));
 }
 
 static void xenoprof_reset_stat(void)
@@ -56,6 +67,7 @@ static void xenoprof_reset_stat(void)
     corrupted_buffer_samples = 0;
     lost_samples = 0;
     active_samples = 0;
+    passive_samples = 0;
     idle_samples = 0;
     others_samples = 0;
 }
@@ -83,13 +95,122 @@ static void xenoprof_reset_buf(struct do
     }
 }
 
+char *alloc_xenoprof_buf(struct domain *d, int npages)
+{
+    char *rawbuf;
+    int i, order;
+
+    /* allocate pages to store sample buffer shared with domain */
+    order  = get_order_from_pages(npages);
+    rawbuf = alloc_xenheap_pages(order);
+    if ( rawbuf == NULL )
+    {
+        printk("alloc_xenoprof_buf(): memory allocation failed\n");
+        return 0;
+    }
+
+    /* Share pages so that kernel can map it */
+    for ( i = 0; i < npages; i++ )
+        share_xen_page_with_guest(
+            virt_to_page(rawbuf + i * PAGE_SIZE), 
+            d, XENSHARE_writable);
+
+    return rawbuf;
+}
+
+int alloc_xenoprof_struct(struct domain *d, int max_samples, int is_passive)
+{
+    struct vcpu *v;
+    int nvcpu, npages, bufsize, max_bufsize;
+    int i;
+
+    d->xenoprof = xmalloc(struct xenoprof);
+
+    if ( d->xenoprof == NULL )
+    {
+        printk ("alloc_xenoprof_struct(): memory "
+                "allocation (xmalloc) failed\n");
+        return -ENOMEM;
+    }
+
+    memset(d->xenoprof, 0, sizeof(*d->xenoprof));
+
+    nvcpu = 0;
+    for_each_vcpu ( d, v )
+        nvcpu++;
+
+    /* reduce buffer size if necessary to limit pages allocated */
+    bufsize = sizeof(struct xenoprof_buf) +
+        (max_samples - 1) * sizeof(struct event_log);
+    max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu;
+    if ( bufsize > max_bufsize )
+    {
+        bufsize = max_bufsize;
+        max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) /
+                        sizeof(struct event_log) ) + 1;
+    }
+
+    npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1;
+    
+    d->xenoprof->rawbuf = alloc_xenoprof_buf(is_passive ? dom0 : d, npages);
+
+    if ( d->xenoprof->rawbuf == NULL )
+    {
+        xfree(d->xenoprof);
+        d->xenoprof = NULL;
+        return -ENOMEM;
+    }
+
+    d->xenoprof->npages = npages;
+    d->xenoprof->nbuf = nvcpu;
+    d->xenoprof->bufsize = bufsize;
+    d->xenoprof->domain_ready = 0;
+    d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED;
+
+    /* Update buffer pointers for active vcpus */
+    i = 0;
+    for_each_vcpu ( d, v )
+    {
+        d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples;
+        d->xenoprof->vcpu[v->vcpu_id].buffer =
+            (struct xenoprof_buf *)&d->xenoprof->rawbuf[i * bufsize];
+        d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples;
+        d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id;
+
+        i++;
+        /* in the unlikely case that the number of active vcpus changes */
+        if ( i >= nvcpu )
+            break;
+    }
+    
+    return 0;
+}
+
+void free_xenoprof_pages(struct domain *d)
+{
+    struct xenoprof *x;
+    int order;
+
+    x = d->xenoprof;
+    if ( x == NULL )
+        return;
+
+    if ( x->rawbuf != NULL )
+    {
+        order = get_order_from_pages(x->npages);
+        free_xenheap_pages(x->rawbuf, order);
+    }
+
+    xfree(x);
+    d->xenoprof = NULL;
+}
+
 int active_index(struct domain *d)
 {
     int i;
-    domid_t id = d->domain_id;
 
     for ( i = 0; i < adomains; i++ )
-        if ( active_domains[i] == id )
+        if ( active_domains[i] == d )
             return i;
 
     return -1;
@@ -132,47 +253,116 @@ int reset_active(struct domain *d)
     x->domain_ready = 0;
     x->domain_type = XENOPROF_DOMAIN_IGNORED;
     active_ready[ind] = 0;
+    active_domains[ind] = NULL;
     activated--;
+    put_domain(d); 
+
     if ( activated <= 0 )
         adomains = 0;
 
     return 0;
 }
 
-int reset_active_list(void)
+void reset_passive(struct domain *d)
+{
+    struct xenoprof *x;
+
+    if (d==0)
+        return;
+
+    x = d->xenoprof;
+    if ( x == NULL )
+        return;
+
+    x->domain_type = XENOPROF_DOMAIN_IGNORED;
+
+    return;
+}
+
+void reset_active_list(void)
 {
     int i;
-    struct domain *d;
 
     for ( i = 0; i < adomains; i++ )
     {
         if ( active_ready[i] )
         {
-            d = find_domain_by_id(active_domains[i]);
-            if ( d != NULL )
-            {
-                reset_active(d);
-                put_domain(d);
-            }
+            reset_active(active_domains[i]);
         }
     }
 
     adomains = 0;
     activated = 0;
-
-    return 0;
+}
+
+void reset_passive_list(void)
+{
+    int i;
+
+    for ( i = 0; i < pdomains; i++ )
+    {
+        reset_passive(passive_domains[i]);
+        put_domain(passive_domains[i]);
+        passive_domains[i] = NULL;
+    }
+
+    pdomains = 0;
 }
 
 int add_active_list (domid_t domid)
 {
+    struct domain *d;
+
     if ( adomains >= MAX_OPROF_DOMAINS )
         return -E2BIG;
 
-    active_domains[adomains] = domid;
+    d = find_domain_by_id(domid); 
+    if ( d == NULL )
+        return -EINVAL;
+
+    active_domains[adomains] = d;
     active_ready[adomains] = 0;
     adomains++;
 
     return 0;
+}
+
+int add_passive_list(XEN_GUEST_HANDLE(void) arg)
+{
+    struct xenoprof_passive passive;
+    struct domain *d;
+    int ret = 0;
+
+    if ( pdomains >= MAX_OPROF_DOMAINS )
+        return -E2BIG;
+
+    if ( copy_from_guest(&passive, arg, 1) )
+        return -EFAULT;
+
+    d = find_domain_by_id(passive.domain_id); 
+    if ( d == NULL )
+        return -EINVAL;
+
+    if ( (d->xenoprof == NULL) && 
+         ((ret = alloc_xenoprof_struct(d, passive.max_samples, 1)) < 0) ) {
+        put_domain(d);
+        return -ENOMEM;
+    }
+
+    d->xenoprof->domain_type = XENOPROF_DOMAIN_PASSIVE;
+    passive.nbuf = d->xenoprof->nbuf;
+    passive.bufsize = d->xenoprof->bufsize;
+    passive.buf_maddr = __pa(d->xenoprof->rawbuf);
+
+    if ( copy_to_guest(arg, &passive, 1) ) {
+        put_domain(d);
+        return -EFAULT;
+    }
+    
+    passive_domains[pdomains] = d;
+    pdomains++;
+
+    return ret;
 }
 
 void xenoprof_log_event(
@@ -231,7 +421,10 @@ void xenoprof_log_event(
         if ( head >= size )
             head = 0;
         buf->event_head = head;
-        active_samples++;
+        if ( is_active(vcpu->domain) )
+            active_samples++;
+        else
+            passive_samples++;
         if ( mode == 0 )
             buf->user_samples++;
         else if ( mode == 1 )
@@ -241,114 +434,6 @@ void xenoprof_log_event(
     }
 }
 
-char *alloc_xenoprof_buf(struct domain *d, int npages)
-{
-    char *rawbuf;
-    int i, order;
-
-    /* allocate pages to store sample buffer shared with domain */
-    order  = get_order_from_pages(npages);
-    rawbuf = alloc_xenheap_pages(order);
-    if ( rawbuf == NULL )
-    {
-        printk("alloc_xenoprof_buf(): memory allocation failed\n");
-        return 0;
-    }
-
-    /* Share pages so that kernel can map it */
-    for ( i = 0; i < npages; i++ )
-        share_xen_page_with_guest(
-            virt_to_page(rawbuf + i * PAGE_SIZE), 
-            d, XENSHARE_writable);
-
-    return rawbuf;
-}
-
-int alloc_xenoprof_struct(struct domain *d, int max_samples)
-{
-    struct vcpu *v;
-    int nvcpu, npages, bufsize, max_bufsize;
-    int i;
-
-    d->xenoprof = xmalloc(struct xenoprof);
-
-    if ( d->xenoprof == NULL )
-    {
-        printk ("alloc_xenoprof_struct(): memory "
-                "allocation (xmalloc) failed\n");
-        return -ENOMEM;
-    }
-
-    memset(d->xenoprof, 0, sizeof(*d->xenoprof));
-
-    nvcpu = 0;
-    for_each_vcpu ( d, v )
-        nvcpu++;
-
-    /* reduce buffer size if necessary to limit pages allocated */
-    bufsize = sizeof(struct xenoprof_buf) +
-        (max_samples - 1) * sizeof(struct event_log);
-    max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu;
-    if ( bufsize > max_bufsize )
-    {
-        bufsize = max_bufsize;
-        max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) /
-                        sizeof(struct event_log) ) + 1;
-    }
-
-    npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1;
-    d->xenoprof->rawbuf = alloc_xenoprof_buf(d, npages);
-    if ( d->xenoprof->rawbuf == NULL )
-    {
-        xfree(d->xenoprof);
-        d->xenoprof = NULL;
-        return -ENOMEM;
-    }
-
-    d->xenoprof->npages = npages;
-    d->xenoprof->nbuf = nvcpu;
-    d->xenoprof->bufsize = bufsize;
-    d->xenoprof->domain_ready = 0;
-    d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED;
-
-    /* Update buffer pointers for active vcpus */
-    i = 0;
-    for_each_vcpu ( d, v )
-    {
-        d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples;
-        d->xenoprof->vcpu[v->vcpu_id].buffer =
-            (struct xenoprof_buf *)&d->xenoprof->rawbuf[i * bufsize];
-        d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples;
-        d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id;
-
-        i++;
-        /* in the unlikely case that the number of active vcpus changes */
-        if ( i >= nvcpu )
-            break;
-    }
-
-    return 0;
-}
-
-void free_xenoprof_pages(struct domain *d)
-{
-    struct xenoprof *x;
-    int order;
-
-    x = d->xenoprof;
-    if ( x == NULL )
-        return;
-
-    if ( x->rawbuf != NULL )
-    {
-        order = get_order_from_pages(x->npages);
-        free_xenheap_pages(x->rawbuf, order);
-    }
-
-    xfree(x);
-    d->xenoprof = NULL;
-}
-
 int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
 {
     struct xenoprof_init xenoprof_init;
@@ -373,7 +458,7 @@ int xenoprof_op_init(XEN_GUEST_HANDLE(vo
      * is called. Memory is then kept until domain is destroyed.
      */
     if ( (d->xenoprof == NULL) &&
-         ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples)) < 0) )
+         ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples, 0)) < 0) )
         goto err;
 
     xenoprof_reset_buf(d);
@@ -429,7 +514,14 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
 
     case XENOPROF_reset_active_list:
     {
-        ret = reset_active_list();
+        reset_active_list();
+        ret = 0;
+        break;
+    }
+    case XENOPROF_reset_passive_list:
+    {
+        reset_passive_list();
+        ret = 0;
         break;
     }
     case XENOPROF_set_active:
@@ -440,6 +532,13 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
         if ( copy_from_guest(&domid, arg, 1) )
             return -EFAULT;
         ret = add_active_list(domid);
+        break;
+    }
+    case XENOPROF_set_passive:
+    {
+        if ( xenoprof_state != XENOPROF_IDLE )
+            return -EPERM;
+        ret = add_passive_list(arg);
         break;
     }
     case XENOPROF_reserve_counters:
@@ -484,14 +583,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
         break;
 
     case XENOPROF_enable_virq:
+    {
+        int i;
         if ( current->domain == primary_profiler )
         {
             nmi_enable_virq();
             xenoprof_reset_stat();
+            for ( i = 0; i < pdomains; i++ ) {
+                xenoprof_reset_buf(passive_domains[i]);
+            }
         }
         xenoprof_reset_buf(current->domain);
         ret = set_active(current->domain);
         break;
+    }
 
     case XENOPROF_start:
         ret = -EPERM;
@@ -525,6 +630,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
             xenoprof_state = XENOPROF_IDLE;
             nmi_release_counters();
             nmi_disable_virq();
+            reset_passive_list();
             ret = 0;
         }
         break;
diff -r b12cd185d579 -r 23591d2c46aa xen/include/public/xenoprof.h
--- a/xen/include/public/xenoprof.h     Tue Jun 27 11:17:14 2006 +0100
+++ b/xen/include/public/xenoprof.h     Tue Jun 27 11:23:06 2006 +0100
@@ -80,6 +80,15 @@ typedef struct xenoprof_counter xenoprof
 typedef struct xenoprof_counter xenoprof_counter_t;
 DEFINE_XEN_GUEST_HANDLE(xenoprof_counter_t);
 
+typedef struct xenoprof_passive {
+    uint16_t domain_id;
+    int32_t  max_samples;
+    int32_t  nbuf;
+    int32_t  bufsize;
+    uint64_t buf_maddr;
+} xenoprof_passive_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
+
 
 #endif /* __XEN_PUBLIC_XENOPROF_H__ */
 
diff -r b12cd185d579 -r 23591d2c46aa xen/include/xen/xenoprof.h
--- a/xen/include/xen/xenoprof.h        Tue Jun 27 11:17:14 2006 +0100
+++ b/xen/include/xen/xenoprof.h        Tue Jun 27 11:23:06 2006 +0100
@@ -14,6 +14,7 @@
 
 #define XENOPROF_DOMAIN_IGNORED    0
 #define XENOPROF_DOMAIN_ACTIVE     1
+#define XENOPROF_DOMAIN_PASSIVE    2
 
 #define XENOPROF_IDLE              0
 #define XENOPROF_COUNTERS_RESERVED 1

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.