rpms/kernel/devel config-generic, 1.238.6.20, 1.238.6.21 kernel.spec, 1.1294.2.27, 1.1294.2.28 xen.pvops.patch, 1.1.2.21, 1.1.2.22 xen.pvops.post.patch, 1.1.2.14, 1.1.2.15 xen.pvops.pre.patch, 1.1.2.11, 1.1.2.12

Michael Young myoung at fedoraproject.org
Fri May 22 20:02:54 UTC 2009


Author: myoung

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv30286

Modified Files:
      Tag: private-myoung-dom0-branch
	config-generic kernel.spec xen.pvops.patch 
	xen.pvops.post.patch xen.pvops.pre.patch 
Log Message:
enable PERF_COUNTERS to get pvops kernel to build



Index: config-generic
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/config-generic,v
retrieving revision 1.238.6.20
retrieving revision 1.238.6.21
diff -u -p -r1.238.6.20 -r1.238.6.21
--- config-generic	21 May 2009 22:11:56 -0000	1.238.6.20
+++ config-generic	22 May 2009 20:02:04 -0000	1.238.6.21
@@ -3958,7 +3958,7 @@ CONFIG_STRIP_ASM_SYMS=y
 #
 # added for xen pvops patch
 #
-# CONFIG_PERF_COUNTERS is not set
+CONFIG_PERF_COUNTERS=y
 CONFIG_XEN_DOM0=y
 CONFIG_XEN_DEV_EVTCHN=m
 CONFIG_ALLOW_WARNINGS=y


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.1294.2.27
retrieving revision 1.1294.2.28
diff -u -p -r1.1294.2.27 -r1.1294.2.28
--- kernel.spec	22 May 2009 18:09:38 -0000	1.1294.2.27
+++ kernel.spec	22 May 2009 20:02:04 -0000	1.1294.2.28
@@ -1829,6 +1829,7 @@ fi
 * Fri May 22 2009 Michael Young <m.a.young at durham.ac.uk>
 - update pvops patch to latest xen-tip/next version
 - pull in patch for !PERF_COUNTERS build failure
+- That still doesn't work so enable PERF_COUNTERS for the moment
 
 * Thu May 21 2009 Michael Young <m.a.young at durham.ac.uk>
 - update pvops patch to latest xen-tip/next version

xen.pvops.patch:

Index: xen.pvops.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/Attic/xen.pvops.patch,v
retrieving revision 1.1.2.21
retrieving revision 1.1.2.22
diff -u -p -r1.1.2.21 -r1.1.2.22
--- xen.pvops.patch	22 May 2009 18:09:38 -0000	1.1.2.21
+++ xen.pvops.patch	22 May 2009 20:02:04 -0000	1.1.2.22
@@ -6283,7 +6283,7 @@ index 0000000..594d270
 +}
 diff --git a/Documentation/perf_counter/perf.h b/Documentation/perf_counter/perf.h
 new file mode 100644
-index 0000000..6fa3656
+index 0000000..81a7374
 --- /dev/null
 +++ b/Documentation/perf_counter/perf.h
 @@ -0,0 +1,62 @@
@@ -6343,8 +6343,8 @@ index 0000000..6fa3656
 +		       group_fd, flags);
 +}
 +
-+#define MAX_COUNTERS			64
-+#define MAX_NR_CPUS			256
++#define MAX_COUNTERS			1024
++#define MAX_NR_CPUS			4096
 +
 +#define EID(type, id) (((__u64)(type) << PERF_COUNTER_TYPE_SHIFT) | (id))
 +
@@ -17391,7 +17391,7 @@ index 8c86b72..1b68659 100644
  # drivers-y are linked after core-y
  drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
 diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
-index 6633b6e..8979283 100644
+index 6633b6e..8d16ada 100644
 --- a/arch/x86/boot/Makefile
 +++ b/arch/x86/boot/Makefile
 @@ -26,9 +26,10 @@ targets		:= vmlinux.bin setup.bin setup.elf bzImage
@@ -17426,7 +17426,7 @@ index 6633b6e..8979283 100644
 +$(obj)/voffset.h: vmlinux FORCE
 +	$(call if_changed,voffset)
 +
-+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
++sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 +
 +quiet_cmd_zoffset = ZOFFSET $@
 +      cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
@@ -18849,7 +18849,7 @@ index 1aae8f3..c501a5b 100644
  
  	return 0;
 diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
-index 5d84d1c..25fc36b 100644
+index 5d84d1c..b31cc54 100644
 --- a/arch/x86/boot/header.S
 +++ b/arch/x86/boot/header.S
 @@ -22,7 +22,8 @@
@@ -18908,7 +18908,7 @@ index 5d84d1c..25fc36b 100644
  
 +pref_address:		.quad LOAD_PHYSICAL_ADDR	# preferred load addr
 +
-+#define ZO_INIT_SIZE	(ZO__end - ZO_startup_32 + ZO_extract_offset)
++#define ZO_INIT_SIZE	(ZO__end - ZO_startup_32 + ZO_z_extract_offset)
 +#define VO_INIT_SIZE	(VO__end - VO__text)
 +#if ZO_INIT_SIZE > VO_INIT_SIZE
 +#define INIT_SIZE ZO_INIT_SIZE
@@ -25709,10 +25709,18 @@ index 0000000..6206033
 @@ -0,0 +1 @@
 +#include "../../../boot/regs.c"
 diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
-index f287092..9376ff4 100644
+index f287092..9e2c551 100644
 --- a/arch/x86/kernel/apic/apic.c
 +++ b/arch/x86/kernel/apic/apic.c
-@@ -34,6 +34,7 @@
+@@ -14,6 +14,7 @@
+  *	Mikael Pettersson	:	PM converted to driver model.
+  */
+ 
++#include <linux/perf_counter.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/acpi_pmtmr.h>
+@@ -34,6 +35,7 @@
  #include <linux/smp.h>
  #include <linux/mm.h>
  
@@ -25720,7 +25728,7 @@ index f287092..9376ff4 100644
  #include <asm/pgalloc.h>
  #include <asm/atomic.h>
  #include <asm/mpspec.h>
-@@ -98,6 +99,29 @@ early_param("lapic", parse_lapic);
+@@ -98,6 +100,29 @@ early_param("lapic", parse_lapic);
  /* Local APIC was disabled by the BIOS and enabled by the kernel */
  static int enabled_via_apicbase;
  
@@ -25750,7 +25758,7 @@ index f287092..9376ff4 100644
  #endif
  
  #ifdef CONFIG_X86_64
-@@ -111,13 +135,19 @@ static __init int setup_apicpmtimer(char *s)
+@@ -111,13 +136,19 @@ static __init int setup_apicpmtimer(char *s)
  __setup("apicpmtimer", setup_apicpmtimer);
  #endif
  
@@ -25771,7 +25779,7 @@ index f287092..9376ff4 100644
  	disable_x2apic = 1;
  	setup_clear_cpu_cap(X86_FEATURE_X2APIC);
  	return 0;
-@@ -209,6 +239,31 @@ static int modern_apic(void)
+@@ -209,6 +240,31 @@ static int modern_apic(void)
  	return lapic_get_version() >= 0x14;
  }
  
@@ -25803,7 +25811,7 @@ index f287092..9376ff4 100644
  void native_apic_wait_icr_idle(void)
  {
  	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
-@@ -348,7 +403,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
+@@ -348,7 +404,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
  
  static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
  {
@@ -25812,7 +25820,7 @@ index f287092..9376ff4 100644
  	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
  
  	apic_write(reg, v);
-@@ -761,6 +816,8 @@ static void local_apic_timer_interrupt(void)
+@@ -761,6 +817,8 @@ static void local_apic_timer_interrupt(void)
  	inc_irq_stat(apic_timer_irqs);
  
  	evt->event_handler(evt);
@@ -25821,7 +25829,7 @@ index f287092..9376ff4 100644
  }
  
  /*
-@@ -815,7 +872,7 @@ void clear_local_APIC(void)
+@@ -815,7 +873,7 @@ void clear_local_APIC(void)
  	u32 v;
  
  	/* APIC hasn't been mapped yet */
@@ -25830,7 +25838,7 @@ index f287092..9376ff4 100644
  		return;
  
  	maxlvt = lapic_get_maxlvt();
-@@ -1133,6 +1190,7 @@ void __cpuinit setup_local_APIC(void)
+@@ -1133,6 +1191,7 @@ void __cpuinit setup_local_APIC(void)
  		apic_write(APIC_ESR, 0);
  	}
  #endif
@@ -25838,7 +25846,7 @@ index f287092..9376ff4 100644
  
  	preempt_disable();
  
-@@ -1287,7 +1345,7 @@ void check_x2apic(void)
+@@ -1287,7 +1346,7 @@ void check_x2apic(void)
  {
  	if (x2apic_enabled()) {
  		pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
@@ -25847,7 +25855,7 @@ index f287092..9376ff4 100644
  	}
  }
  
-@@ -1295,7 +1353,7 @@ void enable_x2apic(void)
+@@ -1295,7 +1354,7 @@ void enable_x2apic(void)
  {
  	int msr, msr2;
  
@@ -25856,7 +25864,7 @@ index f287092..9376ff4 100644
  		return;
  
  	rdmsr(MSR_IA32_APICBASE, msr, msr2);
-@@ -1304,6 +1362,7 @@ void enable_x2apic(void)
+@@ -1304,6 +1363,7 @@ void enable_x2apic(void)
  		wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
  	}
  }
@@ -25864,7 +25872,7 @@ index f287092..9376ff4 100644
  
  void __init enable_IR_x2apic(void)
  {
-@@ -1312,32 +1371,21 @@ void __init enable_IR_x2apic(void)
+@@ -1312,32 +1372,21 @@ void __init enable_IR_x2apic(void)
  	unsigned long flags;
  	struct IO_APIC_route_entry **ioapic_entries = NULL;
  
@@ -25907,7 +25915,7 @@ index f287092..9376ff4 100644
  		return;
  	}
  
-@@ -1357,19 +1405,16 @@ void __init enable_IR_x2apic(void)
+@@ -1357,19 +1406,16 @@ void __init enable_IR_x2apic(void)
  	mask_IO_APIC_setup(ioapic_entries);
  	mask_8259A();
  
@@ -25933,7 +25941,7 @@ index f287092..9376ff4 100644
  	}
  
  end_restore:
-@@ -1378,37 +1423,34 @@ end_restore:
+@@ -1378,37 +1424,34 @@ end_restore:
  		 * IR enabling failed
  		 */
  		restore_IO_APIC_setup(ioapic_entries);
@@ -25982,7 +25990,7 @@ index f287092..9376ff4 100644
  
  #ifdef CONFIG_X86_64
  /*
-@@ -1425,7 +1467,6 @@ static int __init detect_init_APIC(void)
+@@ -1425,7 +1468,6 @@ static int __init detect_init_APIC(void)
  	}
  
  	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
@@ -25990,7 +25998,7 @@ index f287092..9376ff4 100644
  	return 0;
  }
  #else
-@@ -1539,32 +1580,42 @@ void __init early_init_lapic_mapping(void)
+@@ -1539,32 +1581,42 @@ void __init early_init_lapic_mapping(void)
   */
  void __init init_apic_mappings(void)
  {
@@ -26047,7 +26055,7 @@ index f287092..9376ff4 100644
  }
  
  /*
-@@ -1733,8 +1784,7 @@ void __init connect_bsp_APIC(void)
+@@ -1733,8 +1785,7 @@ void __init connect_bsp_APIC(void)
  		 */
  		apic_printk(APIC_VERBOSE, "leaving PIC mode, "
  				"enabling APIC mode.\n");
@@ -26057,7 +26065,7 @@ index f287092..9376ff4 100644
  	}
  #endif
  	if (apic->enable_apic_mode)
-@@ -1762,8 +1812,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
+@@ -1762,8 +1813,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
  		 */
  		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
  				"entering PIC mode.\n");
@@ -26067,7 +26075,7 @@ index f287092..9376ff4 100644
  		return;
  	}
  #endif
-@@ -1969,10 +2018,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
+@@ -1969,10 +2019,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
  
  	local_irq_save(flags);
  	disable_local_APIC();
@@ -26080,7 +26088,7 @@ index f287092..9376ff4 100644
  	local_irq_restore(flags);
  	return 0;
  }
-@@ -1982,8 +2031,6 @@ static int lapic_resume(struct sys_device *dev)
+@@ -1982,8 +2032,6 @@ static int lapic_resume(struct sys_device *dev)
  	unsigned int l, h;
  	unsigned long flags;
  	int maxlvt;
@@ -26089,7 +26097,7 @@ index f287092..9376ff4 100644
  	int ret;
  	struct IO_APIC_route_entry **ioapic_entries = NULL;
  
-@@ -1991,7 +2038,7 @@ static int lapic_resume(struct sys_device *dev)
+@@ -1991,7 +2039,7 @@ static int lapic_resume(struct sys_device *dev)
  		return 0;
  
  	local_irq_save(flags);
@@ -26098,7 +26106,7 @@ index f287092..9376ff4 100644
  		ioapic_entries = alloc_ioapic_entries();
  		if (!ioapic_entries) {
  			WARN(1, "Alloc ioapic_entries in lapic resume failed.");
-@@ -2007,17 +2054,10 @@ static int lapic_resume(struct sys_device *dev)
+@@ -2007,17 +2055,10 @@ static int lapic_resume(struct sys_device *dev)
  
  		mask_IO_APIC_setup(ioapic_entries);
  		mask_8259A();
@@ -26117,7 +26125,7 @@ index f287092..9376ff4 100644
  	else {
  		/*
  		 * Make sure the APICBASE points to the right address
-@@ -2055,20 +2095,15 @@ static int lapic_resume(struct sys_device *dev)
+@@ -2055,20 +2096,15 @@ static int lapic_resume(struct sys_device *dev)
  	apic_write(APIC_ESR, 0);
  	apic_read(APIC_ESR);
  
@@ -26140,7 +26148,7 @@ index f287092..9376ff4 100644
  	return 0;
  }
  
-@@ -2117,31 +2152,14 @@ static void apic_pm_activate(void) { }
+@@ -2117,31 +2153,14 @@ static void apic_pm_activate(void) { }
  #endif	/* CONFIG_PM */
  
  #ifdef CONFIG_X86_64
@@ -26174,7 +26182,7 @@ index f287092..9376ff4 100644
  	bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
  	bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
  
-@@ -2177,18 +2195,67 @@ __cpuinit int apic_is_clustered_box(void)
+@@ -2177,18 +2196,67 @@ __cpuinit int apic_is_clustered_box(void)
  			++zeros;
  	}
  
@@ -35368,6 +35376,25 @@ index 7563b31..af71d06 100644
 +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
 +			quirk_amd_nb_node);
  #endif
+diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
+index 1340dad..667188e 100644
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -232,6 +232,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
+ 			DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"),
+ 		},
+ 	},
++	{	/* Handle problems with rebooting on Sony VGN-Z540N */
++		.callback = set_bios_reboot,
++		.ident = "Sony VGN-Z540N",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
++		},
++	},
+ 	{ }
+ };
+ 
 diff --git a/arch/x86/kernel/scx200_32.c b/arch/x86/kernel/scx200_32.c
 index 7e004ac..1b6e3d1 100644
 --- a/arch/x86/kernel/scx200_32.c
@@ -56284,33 +56311,10 @@ index 0e06c17..8a11f04 100644
  
  #ifdef MODULE
 diff --git a/include/linux/init_task.h b/include/linux/init_task.h
-index d87247d..0d91196 100644
+index d87247d..889bf99 100644
 --- a/include/linux/init_task.h
 +++ b/include/linux/init_task.h
-@@ -108,6 +108,18 @@ extern struct group_info init_groups;
- 
- extern struct cred init_cred;
- 
-+#ifdef CONFIG_PERF_COUNTERS
-+# define INIT_PERF_COUNTERS(tsk)					\
-+	.perf_counter_ctx.counter_list =				\
-+		LIST_HEAD_INIT(tsk.perf_counter_ctx.counter_list),	\
-+	.perf_counter_ctx.event_list =					\
-+		LIST_HEAD_INIT(tsk.perf_counter_ctx.event_list),	\
-+	.perf_counter_ctx.lock =					\
-+		__SPIN_LOCK_UNLOCKED(tsk.perf_counter_ctx.lock),
-+#else
-+# define INIT_PERF_COUNTERS(tsk)
-+#endif
-+
- /*
-  *  INIT_TASK is used to set up the first task table, touch at
-  * your own risk!. Base=0, limit=0x1fffff (=2MB)
-@@ -171,9 +183,11 @@ extern struct cred init_cred;
- 	},								\
- 	.dirties = INIT_PROP_LOCAL_SINGLE(dirties),			\
- 	INIT_IDS							\
-+	INIT_PERF_COUNTERS(tsk)						\
+@@ -174,6 +174,7 @@ extern struct cred init_cred;
  	INIT_TRACE_IRQFLAGS						\
  	INIT_LOCKDEP							\
  	INIT_FTRACE_GRAPH						\
@@ -56949,10 +56953,10 @@ index 72698d8..75b0645 100644
  #endif /* LINUX_PCI_H */
 diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
 new file mode 100644
-index 0000000..9ab322b
+index 0000000..2eedae8
 --- /dev/null
 +++ b/include/linux/perf_counter.h
-@@ -0,0 +1,651 @@
+@@ -0,0 +1,659 @@
 +/*
 + *  Performance counters:
 + *
@@ -57404,7 +57408,6 @@ index 0000000..9ab322b
 +	struct hw_perf_counter		hw;
 +
 +	struct perf_counter_context	*ctx;
-+	struct task_struct		*task;
 +	struct file			*filp;
 +
 +	struct perf_counter		*parent;
@@ -57453,7 +57456,6 @@ index 0000000..9ab322b
 + * Used as a container for task counters and CPU counters as well:
 + */
 +struct perf_counter_context {
-+#ifdef CONFIG_PERF_COUNTERS
 +	/*
 +	 * Protect the states of the counters in the list,
 +	 * nr_active, and the list:
@@ -57470,7 +57472,9 @@ index 0000000..9ab322b
 +	struct list_head	event_list;
 +	int			nr_counters;
 +	int			nr_active;
++	int			nr_enabled;
 +	int			is_active;
++	atomic_t		refcount;
 +	struct task_struct	*task;
 +
 +	/*
@@ -57478,7 +57482,14 @@ index 0000000..9ab322b
 +	 */
 +	u64			time;
 +	u64			timestamp;
-+#endif
++
++	/*
++	 * These fields let us detect when two contexts have both
++	 * been cloned (inherited) from a common ancestor.
++	 */
++	struct perf_counter_context *parent_ctx;
++	u32			parent_gen;
++	u32			generation;
 +};
 +
 +/**
@@ -57509,7 +57520,8 @@ index 0000000..9ab322b
 +extern const struct pmu *hw_perf_counter_init(struct perf_counter *counter);
 +
 +extern void perf_counter_task_sched_in(struct task_struct *task, int cpu);
-+extern void perf_counter_task_sched_out(struct task_struct *task, int cpu);
++extern void perf_counter_task_sched_out(struct task_struct *task,
++					struct task_struct *next, int cpu);
 +extern void perf_counter_task_tick(struct task_struct *task, int cpu);
 +extern void perf_counter_init_task(struct task_struct *child);
 +extern void perf_counter_exit_task(struct task_struct *child);
@@ -57573,7 +57585,7 @@ index 0000000..9ab322b
 +perf_counter_task_sched_in(struct task_struct *task, int cpu)		{ }
 +static inline void
 +perf_counter_task_sched_out(struct task_struct *task,
-+                          struct task_struct *next, int cpu)		{ }
++			    struct task_struct *next, int cpu)		{ }
 +static inline void
 +perf_counter_task_tick(struct task_struct *task, int cpu)		{ }
 +static inline void perf_counter_init_task(struct task_struct *child)	{ }
@@ -57910,17 +57922,10 @@ index e1b7b21..4016b52 100644
  	RB_FL_OVERWRITE		= 1 << 0,
  };
 diff --git a/include/linux/sched.h b/include/linux/sched.h
-index b4c38bc..fe68809 100644
+index b4c38bc..5396cf5 100644
 --- a/include/linux/sched.h
 +++ b/include/linux/sched.h
-@@ -71,12 +71,14 @@ struct sched_param {
- #include <linux/path.h>
- #include <linux/compiler.h>
- #include <linux/completion.h>
-+#include <linux/perf_counter.h>
- #include <linux/pid.h>
- #include <linux/percpu.h>
- #include <linux/topology.h>
+@@ -77,6 +77,7 @@ struct sched_param {
  #include <linux/proportions.h>
  #include <linux/seccomp.h>
  #include <linux/rcupdate.h>
@@ -57928,12 +57933,13 @@ index b4c38bc..fe68809 100644
  #include <linux/rtmutex.h>
  
  #include <linux/time.h>
-@@ -96,8 +98,8 @@ struct exec_domain;
+@@ -96,8 +97,9 @@ struct exec_domain;
  struct futex_pi_state;
  struct robust_list_head;
  struct bio;
 -struct bts_tracer;
  struct fs_struct;
++struct perf_counter_context;
 +struct bts_context;
  
  /*
@@ -58039,15 +58045,17 @@ index b4c38bc..fe68809 100644
  
  	/* PID/PID hash table linkage. */
  	struct pid_link pids[PIDTYPE_MAX];
-@@ -1380,6 +1401,7 @@ struct task_struct {
+@@ -1380,6 +1401,9 @@ struct task_struct {
  	struct list_head pi_state_list;
  	struct futex_pi_state *pi_state_cache;
  #endif
-+	struct perf_counter_context perf_counter_ctx;
++#ifdef CONFIG_PERF_COUNTERS
++	struct perf_counter_context *perf_counter_ctxp;
++#endif
  #ifdef CONFIG_NUMA
  	struct mempolicy *mempolicy;
  	short il_next;
-@@ -1428,7 +1450,9 @@ struct task_struct {
+@@ -1428,7 +1452,9 @@ struct task_struct {
  #ifdef CONFIG_TRACING
  	/* state flags for use by tracers */
  	unsigned long trace;
@@ -58058,7 +58066,7 @@ index b4c38bc..fe68809 100644
  };
  
  /* Future-safe accessor for struct task_struct's cpus_allowed. */
-@@ -2001,8 +2025,10 @@ extern void set_task_comm(struct task_struct *tsk, char *from);
+@@ -2001,8 +2027,10 @@ extern void set_task_comm(struct task_struct *tsk, char *from);
  extern char *get_task_comm(char *to, struct task_struct *tsk);
  
  #ifdef CONFIG_SMP
@@ -58069,7 +58077,7 @@ index b4c38bc..fe68809 100644
  static inline unsigned long wait_task_inactive(struct task_struct *p,
  					       long match_state)
  {
-@@ -2010,7 +2036,8 @@ static inline unsigned long wait_task_inactive(struct task_struct *p,
+@@ -2010,7 +2038,8 @@ static inline unsigned long wait_task_inactive(struct task_struct *p,
  }
  #endif
  
@@ -58079,7 +58087,7 @@ index b4c38bc..fe68809 100644
  
  #define for_each_process(p) \
  	for (p = &init_task ; (p = next_task(p)) != &init_task ; )
-@@ -2049,8 +2076,8 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)
+@@ -2049,8 +2078,8 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)
  
  static inline struct task_struct *next_thread(const struct task_struct *p)
  {
@@ -58090,7 +58098,7 @@ index b4c38bc..fe68809 100644
  }
  
  static inline int thread_group_empty(struct task_struct *p)
-@@ -2388,6 +2415,13 @@ static inline void inc_syscw(struct task_struct *tsk)
+@@ -2388,6 +2417,13 @@ static inline void inc_syscw(struct task_struct *tsk)
  #define TASK_SIZE_OF(tsk)	TASK_SIZE
  #endif
  
@@ -62641,19 +62649,20 @@ index 42d5654..f6c204f 100644
  
  /* compat_time_t is a 32 bit "long" and needs to get converted. */
 diff --git a/kernel/exit.c b/kernel/exit.c
-index abf9cf3..c1cd352 100644
+index abf9cf3..49cdf69 100644
 --- a/kernel/exit.c
 +++ b/kernel/exit.c
-@@ -48,7 +48,7 @@
+@@ -48,7 +48,8 @@
  #include <linux/tracehook.h>
  #include <linux/fs_struct.h>
  #include <linux/init_task.h>
 -#include <trace/sched.h>
++#include <linux/perf_counter.h>
 +#include <trace/events/sched.h>
  
  #include <asm/uaccess.h>
  #include <asm/unistd.h>
-@@ -56,10 +56,6 @@
+@@ -56,10 +57,6 @@
  #include <asm/mmu_context.h>
  #include "cred-internals.h"
  
@@ -62664,17 +62673,17 @@ index abf9cf3..c1cd352 100644
  static void exit_mm(struct task_struct * tsk);
  
  static void __unhash_process(struct task_struct *p)
-@@ -158,6 +154,9 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
+@@ -158,6 +155,9 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
  {
  	struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
  
 +#ifdef CONFIG_PERF_COUNTERS
-+	WARN_ON_ONCE(!list_empty(&tsk->perf_counter_ctx.counter_list));
++	WARN_ON_ONCE(tsk->perf_counter_ctxp);
 +#endif
  	trace_sched_process_free(tsk);
  	put_task_struct(tsk);
  }
-@@ -174,6 +173,7 @@ repeat:
+@@ -174,6 +174,7 @@ repeat:
  	atomic_dec(&__task_cred(p)->user->processes);
  
  	proc_flush_task(p);
@@ -62682,7 +62691,7 @@ index abf9cf3..c1cd352 100644
  	write_lock_irq(&tasklist_lock);
  	tracehook_finish_release_task(p);
  	__exit_signal(p);
-@@ -975,16 +975,19 @@ NORET_TYPE void do_exit(long code)
+@@ -975,16 +976,19 @@ NORET_TYPE void do_exit(long code)
  		module_put(tsk->binfmt->module);
  
  	proc_exit_connector(tsk);
@@ -62707,18 +62716,20 @@ index abf9cf3..c1cd352 100644
  		exit_pi_state_list(tsk);
  	if (unlikely(current->pi_state_cache))
 diff --git a/kernel/fork.c b/kernel/fork.c
-index b9e2edd..60a473e 100644
+index b9e2edd..95a374e 100644
 --- a/kernel/fork.c
 +++ b/kernel/fork.c
-@@ -61,7 +61,6 @@
+@@ -61,8 +61,8 @@
  #include <linux/proc_fs.h>
  #include <linux/blkdev.h>
  #include <linux/fs_struct.h>
 -#include <trace/sched.h>
  #include <linux/magic.h>
++#include <linux/perf_counter.h>
  
  #include <asm/pgtable.h>
-@@ -71,6 +70,8 @@
+ #include <asm/pgalloc.h>
+@@ -71,6 +71,8 @@
  #include <asm/cacheflush.h>
  #include <asm/tlbflush.h>
  
@@ -62727,7 +62738,7 @@ index b9e2edd..60a473e 100644
  /*
   * Protected counters by write_lock_irq(&tasklist_lock)
   */
-@@ -83,8 +84,6 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
+@@ -83,8 +85,6 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
  
  __cacheline_aligned DEFINE_RWLOCK(tasklist_lock);  /* outer */
  
@@ -62736,7 +62747,7 @@ index b9e2edd..60a473e 100644
  int nr_processes(void)
  {
  	int cpu;
-@@ -178,7 +177,7 @@ void __init fork_init(unsigned long mempages)
+@@ -178,7 +178,7 @@ void __init fork_init(unsigned long mempages)
  	/* create a slab on which task_structs can be allocated */
  	task_struct_cachep =
  		kmem_cache_create("task_struct", sizeof(struct task_struct),
@@ -62745,7 +62756,7 @@ index b9e2edd..60a473e 100644
  #endif
  
  	/* do the arch specific task caches init */
-@@ -983,6 +982,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -983,6 +983,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
  		goto fork_out;
  
  	rt_mutex_init_task(p);
@@ -62753,7 +62764,7 @@ index b9e2edd..60a473e 100644
  
  #ifdef CONFIG_PROVE_LOCKING
  	DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
-@@ -1089,8 +1089,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1089,8 +1090,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
  #ifdef CONFIG_DEBUG_MUTEXES
  	p->blocked_on = NULL; /* not blocked yet */
  #endif
@@ -62764,7 +62775,7 @@ index b9e2edd..60a473e 100644
  
  	/* Perform scheduler related setup. Assign this task to a CPU. */
  	sched_fork(p, clone_flags);
-@@ -1461,20 +1461,20 @@ void __init proc_caches_init(void)
+@@ -1461,20 +1462,20 @@ void __init proc_caches_init(void)
  {
  	sighand_cachep = kmem_cache_create("sighand_cache",
  			sizeof(struct sighand_struct), 0,
@@ -64962,10 +64973,10 @@ index 507cf2b..947b3ad 100644
 +EXPORT_SYMBOL(atomic_dec_and_mutex_lock);
 diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
 new file mode 100644
-index 0000000..08584c1
+index 0000000..c100554
 --- /dev/null
 +++ b/kernel/perf_counter.c
-@@ -0,0 +1,3584 @@
+@@ -0,0 +1,3719 @@
 +/*
 + * Performance counter core code
 + *
@@ -65065,6 +65076,20 @@ index 0000000..08584c1
 +		hw_perf_enable();
 +}
 +
++static void get_ctx(struct perf_counter_context *ctx)
++{
++	atomic_inc(&ctx->refcount);
++}
++
++static void put_ctx(struct perf_counter_context *ctx)
++{
++	if (atomic_dec_and_test(&ctx->refcount)) {
++		if (ctx->parent_ctx)
++			put_ctx(ctx->parent_ctx);
++		kfree(ctx);
++	}
++}
++
 +static void
 +list_add_counter(struct perf_counter *counter, struct perf_counter_context *ctx)
 +{
@@ -65084,14 +65109,24 @@ index 0000000..08584c1
 +
 +	list_add_rcu(&counter->event_entry, &ctx->event_list);
 +	ctx->nr_counters++;
++	if (counter->state >= PERF_COUNTER_STATE_INACTIVE)
++		ctx->nr_enabled++;
 +}
 +
++/*
++ * Remove a counter from the lists for its context.
++ * Must be called with counter->mutex and ctx->mutex held.
++ */
 +static void
 +list_del_counter(struct perf_counter *counter, struct perf_counter_context *ctx)
 +{
 +	struct perf_counter *sibling, *tmp;
 +
++	if (list_empty(&counter->list_entry))
++		return;
 +	ctx->nr_counters--;
++	if (counter->state >= PERF_COUNTER_STATE_INACTIVE)
++		ctx->nr_enabled--;
 +
 +	list_del_init(&counter->list_entry);
 +	list_del_rcu(&counter->event_entry);
@@ -65155,6 +65190,22 @@ index 0000000..08584c1
 +}
 +
 +/*
++ * Mark this context as not being a clone of another.
++ * Called when counters are added to or removed from this context.
++ * We also increment our generation number so that anything that
++ * was cloned from this context before this will not match anything
++ * cloned from this context after this.
++ */
++static void unclone_ctx(struct perf_counter_context *ctx)
++{
++	++ctx->generation;
++	if (!ctx->parent_ctx)
++		return;
++	put_ctx(ctx->parent_ctx);
++	ctx->parent_ctx = NULL;
++}
++
++/*
 + * Cross CPU call to remove a performance counter
 + *
 + * We disable the counter on the hardware level first. After that we
@@ -65184,8 +65235,6 @@ index 0000000..08584c1
 +
 +	counter_sched_out(counter, cpuctx, ctx);
 +
-+	counter->task = NULL;
-+
 +	list_del_counter(counter, ctx);
 +
 +	if (!ctx->task) {
@@ -65216,6 +65265,7 @@ index 0000000..08584c1
 +	struct perf_counter_context *ctx = counter->ctx;
 +	struct task_struct *task = ctx->task;
 +
++	unclone_ctx(ctx);
 +	if (!task) {
 +		/*
 +		 * Per cpu counters are removed via an smp call and
@@ -65247,7 +65297,6 @@ index 0000000..08584c1
 +	 */
 +	if (!list_empty(&counter->list_entry)) {
 +		list_del_counter(counter, ctx);
-+		counter->task = NULL;
 +	}
 +	spin_unlock_irq(&ctx->lock);
 +}
@@ -65332,6 +65381,7 @@ index 0000000..08584c1
 +		else
 +			counter_sched_out(counter, cpuctx, ctx);
 +		counter->state = PERF_COUNTER_STATE_OFF;
++		ctx->nr_enabled--;
 +	}
 +
 +	spin_unlock_irqrestore(&ctx->lock, flags);
@@ -65373,6 +65423,7 @@ index 0000000..08584c1
 +	if (counter->state == PERF_COUNTER_STATE_INACTIVE) {
 +		update_counter_times(counter);
 +		counter->state = PERF_COUNTER_STATE_OFF;
++		ctx->nr_enabled--;
 +	}
 +
 +	spin_unlock_irq(&ctx->lock);
@@ -65536,11 +65587,17 @@ index 0000000..08584c1
 +	 * If this is a task context, we need to check whether it is
 +	 * the current task context of this cpu. If not it has been
 +	 * scheduled out before the smp call arrived.
++	 * Or possibly this is the right context but it isn't
++	 * on this cpu because it had no counters.
 +	 */
-+	if (ctx->task && cpuctx->task_ctx != ctx)
-+		return;
++	if (ctx->task && cpuctx->task_ctx != ctx) {
++		if (cpuctx->task_ctx || ctx->task != current)
++			return;
++		cpuctx->task_ctx = ctx;
++	}
 +
 +	spin_lock_irqsave(&ctx->lock, flags);
++	ctx->is_active = 1;
 +	update_context_time(ctx);
 +
 +	/*
@@ -65621,7 +65678,6 @@ index 0000000..08584c1
 +		return;
 +	}
 +
-+	counter->task = task;
 +retry:
 +	task_oncpu_function_call(task, __perf_install_in_context,
 +				 counter);
@@ -65661,10 +65717,14 @@ index 0000000..08584c1
 +	 * If this is a per-task counter, need to check whether this
 +	 * counter's task is the current task on this cpu.
 +	 */
-+	if (ctx->task && cpuctx->task_ctx != ctx)
-+		return;
++	if (ctx->task && cpuctx->task_ctx != ctx) {
++		if (cpuctx->task_ctx || ctx->task != current)
++			return;
++		cpuctx->task_ctx = ctx;
++	}
 +
 +	spin_lock_irqsave(&ctx->lock, flags);
++	ctx->is_active = 1;
 +	update_context_time(ctx);
 +
 +	counter->prev_state = counter->state;
@@ -65672,6 +65732,7 @@ index 0000000..08584c1
 +		goto unlock;
 +	counter->state = PERF_COUNTER_STATE_INACTIVE;
 +	counter->tstamp_enabled = ctx->time - counter->total_time_enabled;
++	ctx->nr_enabled++;
 +
 +	/*
 +	 * If the counter is in a group and isn't the group leader,
@@ -65762,6 +65823,7 @@ index 0000000..08584c1
 +		counter->state = PERF_COUNTER_STATE_INACTIVE;
 +		counter->tstamp_enabled =
 +			ctx->time - counter->total_time_enabled;
++		ctx->nr_enabled++;
 +	}
 + out:
 +	spin_unlock_irq(&ctx->lock);
@@ -65807,6 +65869,25 @@ index 0000000..08584c1
 +}
 +
 +/*
++ * Test whether two contexts are equivalent, i.e. whether they
++ * have both been cloned from the same version of the same context
++ * and they both have the same number of enabled counters.
++ * If the number of enabled counters is the same, then the set
++ * of enabled counters should be the same, because these are both
++ * inherited contexts, therefore we can't access individual counters
++ * in them directly with an fd; we can only enable/disable all
++ * counters via prctl, or enable/disable all counters in a family
++ * via ioctl, which will have the same effect on both contexts.
++ */
++static int context_equiv(struct perf_counter_context *ctx1,
++			 struct perf_counter_context *ctx2)
++{
++	return ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx
++		&& ctx1->parent_gen == ctx2->parent_gen
++		&& ctx1->nr_enabled == ctx2->nr_enabled;
++}
++
++/*
 + * Called from scheduler to remove the counters of the current task,
 + * with interrupts disabled.
 + *
@@ -65817,19 +65898,31 @@ index 0000000..08584c1
 + * accessing the counter control register. If a NMI hits, then it will
 + * not restart the counter.
 + */
-+void perf_counter_task_sched_out(struct task_struct *task, int cpu)
++void perf_counter_task_sched_out(struct task_struct *task,
++				 struct task_struct *next, int cpu)
 +{
 +	struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
-+	struct perf_counter_context *ctx = &task->perf_counter_ctx;
++	struct perf_counter_context *ctx = task->perf_counter_ctxp;
++	struct perf_counter_context *next_ctx;
 +	struct pt_regs *regs;
 +
-+	if (likely(!cpuctx->task_ctx))
++	if (likely(!ctx || !cpuctx->task_ctx))
 +		return;
 +
 +	update_context_time(ctx);
 +
 +	regs = task_pt_regs(task);
 +	perf_swcounter_event(PERF_COUNT_CONTEXT_SWITCHES, 1, 1, regs, 0);
++
++	next_ctx = next->perf_counter_ctxp;
++	if (next_ctx && context_equiv(ctx, next_ctx)) {
++		task->perf_counter_ctxp = next_ctx;
++		next->perf_counter_ctxp = ctx;
++		ctx->task = next;
++		next_ctx->task = task;
++		return;
++	}
++
 +	__perf_counter_sched_out(ctx, cpuctx);
 +
 +	cpuctx->task_ctx = NULL;
@@ -65839,6 +65932,8 @@ index 0000000..08584c1
 +{
 +	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
 +
++	if (!cpuctx->task_ctx)
++		return;
 +	__perf_counter_sched_out(ctx, cpuctx);
 +	cpuctx->task_ctx = NULL;
 +}
@@ -65937,8 +66032,12 @@ index 0000000..08584c1
 +void perf_counter_task_sched_in(struct task_struct *task, int cpu)
 +{
 +	struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
-+	struct perf_counter_context *ctx = &task->perf_counter_ctx;
++	struct perf_counter_context *ctx = task->perf_counter_ctxp;
 +
++	if (likely(!ctx))
++		return;
++	if (cpuctx->task_ctx == ctx)
++		return;
 +	__perf_counter_sched_in(ctx, cpuctx, cpu);
 +	cpuctx->task_ctx = ctx;
 +}
@@ -65953,11 +66052,11 @@ index 0000000..08584c1
 +int perf_counter_task_disable(void)
 +{
 +	struct task_struct *curr = current;
-+	struct perf_counter_context *ctx = &curr->perf_counter_ctx;
++	struct perf_counter_context *ctx = curr->perf_counter_ctxp;
 +	struct perf_counter *counter;
 +	unsigned long flags;
 +
-+	if (likely(!ctx->nr_counters))
++	if (!ctx || !ctx->nr_counters)
 +		return 0;
 +
 +	local_irq_save(flags);
@@ -65988,12 +66087,12 @@ index 0000000..08584c1
 +int perf_counter_task_enable(void)
 +{
 +	struct task_struct *curr = current;
-+	struct perf_counter_context *ctx = &curr->perf_counter_ctx;
++	struct perf_counter_context *ctx = curr->perf_counter_ctxp;
 +	struct perf_counter *counter;
 +	unsigned long flags;
 +	int cpu;
 +
-+	if (likely(!ctx->nr_counters))
++	if (!ctx || !ctx->nr_counters)
 +		return 0;
 +
 +	local_irq_save(flags);
@@ -66096,19 +66195,23 @@ index 0000000..08584c1
 +		return;
 +
 +	cpuctx = &per_cpu(perf_cpu_context, cpu);
-+	ctx = &curr->perf_counter_ctx;
++	ctx = curr->perf_counter_ctxp;
 +
 +	perf_adjust_freq(&cpuctx->ctx);
-+	perf_adjust_freq(ctx);
++	if (ctx)
++		perf_adjust_freq(ctx);
 +
 +	perf_counter_cpu_sched_out(cpuctx);
-+	__perf_counter_task_sched_out(ctx);
++	if (ctx)
++		__perf_counter_task_sched_out(ctx);
 +
 +	rotate_ctx(&cpuctx->ctx);
-+	rotate_ctx(ctx);
++	if (ctx)
++		rotate_ctx(ctx);
 +
 +	perf_counter_cpu_sched_in(cpuctx, cpu);
-+	perf_counter_task_sched_in(curr, cpu);
++	if (ctx)
++		perf_counter_task_sched_in(curr, cpu);
 +}
 +
 +/*
@@ -66144,6 +66247,22 @@ index 0000000..08584c1
 +	return atomic64_read(&counter->count);
 +}
 +
++/*
++ * Initialize the perf_counter context in a task_struct:
++ */
++static void
++__perf_counter_init_context(struct perf_counter_context *ctx,
++			    struct task_struct *task)
++{
++	memset(ctx, 0, sizeof(*ctx));
++	spin_lock_init(&ctx->lock);
++	mutex_init(&ctx->mutex);
++	INIT_LIST_HEAD(&ctx->counter_list);
++	INIT_LIST_HEAD(&ctx->event_list);
++	atomic_set(&ctx->refcount, 1);
++	ctx->task = task;
++}
++
 +static void put_context(struct perf_counter_context *ctx)
 +{
 +	if (ctx->task)
@@ -66154,6 +66273,7 @@ index 0000000..08584c1
 +{
 +	struct perf_cpu_context *cpuctx;
 +	struct perf_counter_context *ctx;
++	struct perf_counter_context *tctx;
 +	struct task_struct *task;
 +
 +	/*
@@ -66193,15 +66313,36 @@ index 0000000..08584c1
 +	if (!task)
 +		return ERR_PTR(-ESRCH);
 +
-+	ctx = &task->perf_counter_ctx;
-+	ctx->task = task;
-+
 +	/* Reuse ptrace permission checks for now. */
 +	if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
-+		put_context(ctx);
++		put_task_struct(task);
 +		return ERR_PTR(-EACCES);
 +	}
 +
++	ctx = task->perf_counter_ctxp;
++	if (!ctx) {
++		ctx = kmalloc(sizeof(struct perf_counter_context), GFP_KERNEL);
++		if (!ctx) {
++			put_task_struct(task);
++			return ERR_PTR(-ENOMEM);
++		}
++		__perf_counter_init_context(ctx, task);
++		/*
++		 * Make sure other cpus see correct values for *ctx
++		 * once task->perf_counter_ctxp is visible to them.
++		 */
++		smp_wmb();
++		tctx = cmpxchg(&task->perf_counter_ctxp, NULL, ctx);
++		if (tctx) {
++			/*
++			 * We raced with some other task; use
++			 * the context they set.
++			 */
++			kfree(ctx);
++			ctx = tctx;
++		}
++	}
++
 +	return ctx;
 +}
 +
@@ -66210,6 +66351,7 @@ index 0000000..08584c1
 +	struct perf_counter *counter;
 +
 +	counter = container_of(head, struct perf_counter, rcu_head);
++	put_ctx(counter->ctx);
 +	kfree(counter);
 +}
 +
@@ -67215,7 +67357,7 @@ index 0000000..08584c1
 +	perf_counter_comm_ctx(&cpuctx->ctx, comm_event);
 +	put_cpu_var(perf_cpu_context);
 +
-+	perf_counter_comm_ctx(&current->perf_counter_ctx, comm_event);
++	perf_counter_comm_ctx(current->perf_counter_ctxp, comm_event);
 +}
 +
 +void perf_counter_comm(struct task_struct *task)
@@ -67224,7 +67366,9 @@ index 0000000..08584c1
 +
 +	if (!atomic_read(&nr_comm_tracking))
 +		return;
-+       
++	if (!current->perf_counter_ctxp)
++		return;
++
 +	comm_event = (struct perf_comm_event){
 +		.task	= task,
 +		.event  = {
@@ -67340,7 +67484,7 @@ index 0000000..08584c1
 +	perf_counter_mmap_ctx(&cpuctx->ctx, mmap_event);
 +	put_cpu_var(perf_cpu_context);
 +
-+	perf_counter_mmap_ctx(&current->perf_counter_ctx, mmap_event);
++	perf_counter_mmap_ctx(current->perf_counter_ctxp, mmap_event);
 +
 +	kfree(buf);
 +}
@@ -67352,6 +67496,8 @@ index 0000000..08584c1
 +
 +	if (!atomic_read(&nr_mmap_tracking))
 +		return;
++	if (!current->perf_counter_ctxp)
++		return;
 +
 +	mmap_event = (struct perf_mmap_event){
 +		.file   = file,
@@ -67953,6 +68099,7 @@ index 0000000..08584c1
 +	counter->group_leader		= group_leader;
 +	counter->pmu			= NULL;
 +	counter->ctx			= ctx;
++	get_ctx(ctx);
 +
 +	counter->state = PERF_COUNTER_STATE_INACTIVE;
 +	if (hw_event->disabled)
@@ -68118,21 +68265,6 @@ index 0000000..08584c1
 +}
 +
 +/*
-+ * Initialize the perf_counter context in a task_struct:
-+ */
-+static void
-+__perf_counter_init_context(struct perf_counter_context *ctx,
-+			    struct task_struct *task)
-+{
-+	memset(ctx, 0, sizeof(*ctx));
-+	spin_lock_init(&ctx->lock);
-+	mutex_init(&ctx->mutex);
-+	INIT_LIST_HEAD(&ctx->counter_list);
-+	INIT_LIST_HEAD(&ctx->event_list);
-+	ctx->task = task;
-+}
-+
-+/*
 + * inherit a counter from parent task to child task:
 + */
 +static struct perf_counter *
@@ -68161,9 +68293,18 @@ index 0000000..08584c1
 +		return child_counter;
 +
 +	/*
++	 * Make the child state follow the state of the parent counter,
++	 * not its hw_event.disabled bit.  We hold the parent's mutex,
++	 * so we won't race with perf_counter_{en,dis}able_family.
++	 */
++	if (parent_counter->state >= PERF_COUNTER_STATE_INACTIVE)
++		child_counter->state = PERF_COUNTER_STATE_INACTIVE;
++	else
++		child_counter->state = PERF_COUNTER_STATE_OFF;
++
++	/*
 +	 * Link it up in the child's context:
 +	 */
-+	child_counter->task = child;
 +	add_counter_to_ctx(child_counter, child_ctx);
 +
 +	child_counter->parent = parent_counter;
@@ -68186,16 +68327,6 @@ index 0000000..08584c1
 +	mutex_lock(&parent_counter->mutex);
 +	list_add_tail(&child_counter->child_list, &parent_counter->child_list);
 +
-+	/*
-+	 * Make the child state follow the state of the parent counter,
-+	 * not its hw_event.disabled bit.  We hold the parent's mutex,
-+	 * so we won't race with perf_counter_{en,dis}able_family.
-+	 */
-+	if (parent_counter->state >= PERF_COUNTER_STATE_INACTIVE)
-+		child_counter->state = PERF_COUNTER_STATE_INACTIVE;
-+	else
-+		child_counter->state = PERF_COUNTER_STATE_OFF;
-+
 +	mutex_unlock(&parent_counter->mutex);
 +
 +	return child_counter;
@@ -68262,40 +68393,15 @@ index 0000000..08584c1
 +	struct perf_counter *parent_counter;
 +
 +	/*
-+	 * If we do not self-reap then we have to wait for the
-+	 * child task to unschedule (it will happen for sure),
-+	 * so that its counter is at its final count. (This
-+	 * condition triggers rarely - child tasks usually get
-+	 * off their CPU before the parent has a chance to
-+	 * get this far into the reaping action)
-+	 */
-+	if (child != current) {
-+		wait_task_inactive(child, 0);
-+		update_counter_times(child_counter);
-+		list_del_counter(child_counter, child_ctx);
-+	} else {
-+		struct perf_cpu_context *cpuctx;
-+		unsigned long flags;
-+
-+		/*
-+		 * Disable and unlink this counter.
-+		 *
-+		 * Be careful about zapping the list - IRQ/NMI context
-+		 * could still be processing it:
-+		 */
-+		local_irq_save(flags);
-+		perf_disable();
-+
-+		cpuctx = &__get_cpu_var(perf_cpu_context);
-+
-+		group_sched_out(child_counter, cpuctx, child_ctx);
-+		update_counter_times(child_counter);
++	 * Protect against concurrent operations on child_counter
++	 * due its fd getting closed, etc.
++	 */
++	mutex_lock(&child_counter->mutex);
 +
-+		list_del_counter(child_counter, child_ctx);
++	update_counter_times(child_counter);
++	list_del_counter(child_counter, child_ctx);
 +
-+		perf_enable();
-+		local_irq_restore(flags);
-+	}
++	mutex_unlock(&child_counter->mutex);
 +
 +	parent_counter = child_counter->parent;
 +	/*
@@ -68314,19 +68420,29 @@ index 0000000..08584c1
 + *
 + * Note: we may be running in child context, but the PID is not hashed
 + * anymore so new counters will not be added.
++ * (XXX not sure that is true when we get called from flush_old_exec.
++ *  -- paulus)
 + */
 +void perf_counter_exit_task(struct task_struct *child)
 +{
 +	struct perf_counter *child_counter, *tmp;
 +	struct perf_counter_context *child_ctx;
++	unsigned long flags;
 +
 +	WARN_ON_ONCE(child != current);
 +
-+	child_ctx = &child->perf_counter_ctx;
++	child_ctx = child->perf_counter_ctxp;
 +
-+	if (likely(!child_ctx->nr_counters))
++	if (likely(!child_ctx))
 +		return;
 +
++	local_irq_save(flags);
++	__perf_counter_task_sched_out(child_ctx);
++	child->perf_counter_ctxp = NULL;
++	local_irq_restore(flags);
++
++	mutex_lock(&child_ctx->mutex);
++
 +again:
 +	list_for_each_entry_safe(child_counter, tmp, &child_ctx->counter_list,
 +				 list_entry)
@@ -68339,6 +68455,10 @@ index 0000000..08584c1
 +	 */
 +	if (!list_empty(&child_ctx->counter_list))
 +		goto again;
++
++	mutex_unlock(&child_ctx->mutex);
++
++	put_ctx(child_ctx);
 +}
 +
 +/*
@@ -68349,20 +68469,27 @@ index 0000000..08584c1
 +	struct perf_counter_context *child_ctx, *parent_ctx;
 +	struct perf_counter *counter;
 +	struct task_struct *parent = current;
++	int inherited_all = 1;
 +
-+	child_ctx  =  &child->perf_counter_ctx;
-+	parent_ctx = &parent->perf_counter_ctx;
-+
-+	__perf_counter_init_context(child_ctx, child);
++	child->perf_counter_ctxp = NULL;
 +
 +	/*
 +	 * This is executed from the parent task context, so inherit
-+	 * counters that have been marked for cloning:
++	 * counters that have been marked for cloning.
++	 * First allocate and initialize a context for the child.
 +	 */
 +
-+	if (likely(!parent_ctx->nr_counters))
++	child_ctx = kmalloc(sizeof(struct perf_counter_context), GFP_KERNEL);
++	if (!child_ctx)
++		return;
++
++	parent_ctx = parent->perf_counter_ctxp;
++	if (likely(!parent_ctx || !parent_ctx->nr_counters))
 +		return;
 +
++	__perf_counter_init_context(child_ctx, child);
++	child->perf_counter_ctxp = child_ctx;
++
 +	/*
 +	 * Lock the parent list. No need to lock the child - not PID
 +	 * hashed yet and not running, so nobody can access it.
@@ -68377,12 +68504,31 @@ index 0000000..08584c1
 +		if (counter != counter->group_leader)
 +			continue;
 +
-+		if (!counter->hw_event.inherit)
++		if (!counter->hw_event.inherit) {
++			inherited_all = 0;
 +			continue;
++		}
 +
 +		if (inherit_group(counter, parent,
-+				  parent_ctx, child, child_ctx))
++				  parent_ctx, child, child_ctx)) {
++			inherited_all = 0;
 +			break;
++		}
++	}
++
++	if (inherited_all) {
++		/*
++		 * Mark the child context as a clone of the parent
++		 * context, or of whatever the parent is a clone of.
++		 */
++		if (parent_ctx->parent_ctx) {
++			child_ctx->parent_ctx = parent_ctx->parent_ctx;
++			child_ctx->parent_gen = parent_ctx->parent_gen;
++		} else {
++			child_ctx->parent_ctx = parent_ctx;
++			child_ctx->parent_gen = parent_ctx->generation;
++		}
++		get_ctx(child_ctx->parent_ctx);
 +	}
 +
 +	mutex_unlock(&parent_ctx->mutex);
@@ -69309,7 +69455,7 @@ index e124bf5..97a2f81 100644
  #ifdef CONFIG_DEBUG_RT_MUTEXES
  # include "rtmutex-debug.h"
 diff --git a/kernel/sched.c b/kernel/sched.c
-index 26efa47..c036590 100644
+index 26efa47..f93305b 100644
 --- a/kernel/sched.c
 +++ b/kernel/sched.c
 @@ -39,6 +39,7 @@
@@ -69837,7 +69983,7 @@ index 26efa47..c036590 100644
  
  	if (likely(prev != next)) {
  		sched_info_switch(prev, next);
-+		perf_counter_task_sched_out(prev, cpu);
++		perf_counter_task_sched_out(prev, next, cpu);
  
  		rq->nr_switches++;
  		rq->curr = next;

xen.pvops.post.patch:

Index: xen.pvops.post.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/Attic/xen.pvops.post.patch,v
retrieving revision 1.1.2.14
retrieving revision 1.1.2.15
diff -u -p -r1.1.2.14 -r1.1.2.15
--- xen.pvops.post.patch	21 May 2009 22:12:01 -0000	1.1.2.14
+++ xen.pvops.post.patch	22 May 2009 20:02:09 -0000	1.1.2.15
@@ -50,16 +50,6 @@ Test some patches to get STACKPROTECTOR 
  static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
  #endif
  
---- a/include/linux/init_task.h	2009-04-23 20:13:50.000000000 +0100
-+++ b/include/linux/init_task.h	2009-04-24 20:47:17.000000000 +0100
-@@ -170,6 +170,7 @@
- 		[PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),		\
- 	},								\
- 	.dirties = INIT_PROP_LOCAL_SINGLE(dirties),			\
-+	INIT_UTRACE(tsk)						\
- 	INIT_IDS							\
- 	INIT_PERF_COUNTERS(tsk)						\
- 	INIT_TRACE_IRQFLAGS						\
 diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
 index 7727aa8..5d6083c 100644
 --- a/arch/x86/include/asm/paravirt_types.h

xen.pvops.pre.patch:

Index: xen.pvops.pre.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/Attic/xen.pvops.pre.patch,v
retrieving revision 1.1.2.11
retrieving revision 1.1.2.12
diff -u -p -r1.1.2.11 -r1.1.2.12
--- xen.pvops.pre.patch	21 May 2009 22:12:01 -0000	1.1.2.11
+++ xen.pvops.pre.patch	22 May 2009 20:02:09 -0000	1.1.2.12
@@ -2,7 +2,6 @@ temporarily revert various Fedora change
 Affected patches;
 more linux-2.6-execshield.patch - arch/x86/mm/init.c arch/x86/mm/init_32.c include/linux/sched.h mm/mmap.c arch/x86/include/asm/paravirt.h arch/x86/kernel/process_32.c
 linux-2.6-defaults-pci_no_msi.patch - drivers/pci/pci.h
-linux-2.6-utrace.patch - include/linux/init_task.h
 
 --- a/arch/x86/mm/init.c	2009-04-24 20:27:42.000000000 +0100
 +++ b/arch/x86/mm/init.c	2009-04-23 20:13:34.000000000 +0100
@@ -86,16 +85,6 @@ linux-2.6-utrace.patch - include/linux/i
  static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
  #endif
  
---- a/include/linux/init_task.h	2009-04-24 20:47:17.000000000 +0100
-+++ b/include/linux/init_task.h	2009-04-23 20:13:50.000000000 +0100
-@@ -170,7 +170,6 @@
- 		[PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),		\
- 	},								\
- 	.dirties = INIT_PROP_LOCAL_SINGLE(dirties),			\
--	INIT_UTRACE(tsk)						\
- 	INIT_IDS							\
- 	INIT_TRACE_IRQFLAGS						\
- 	INIT_LOCKDEP							\
 diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
 index 7727aa8..5d6083c 100644
 --- a/arch/x86/include/asm/paravirt.h




More information about the fedora-extras-commits mailing list