]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/x86/kernel/cpu/perf_event.c
Merge remote-tracking branch 'powerpc/next'
[karo-tx-linux.git] / arch / x86 / kernel / cpu / perf_event.c
index 9469dfa556074db4dff41212a4873b31d5907772..4562cf070c279d5edeb0e18ae94c8bff94166dd8 100644 (file)
@@ -1175,7 +1175,7 @@ static int x86_pmu_add(struct perf_event *event, int flags)
         * skip the schedulability test here, it will be performed
         * at commit time (->commit_txn) as a whole.
         */
-       if (cpuc->group_flag & PERF_EVENT_TXN)
+       if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
                goto done_collect;
 
        ret = x86_pmu.schedule_events(cpuc, n, assign);
@@ -1326,7 +1326,7 @@ static void x86_pmu_del(struct perf_event *event, int flags)
         * XXX assumes any ->del() called during a TXN will only be on
         * an event added during that same TXN.
         */
-       if (cpuc->group_flag & PERF_EVENT_TXN)
+       if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
                return;
 
        /*
@@ -1551,7 +1551,7 @@ static void __init filter_events(struct attribute **attrs)
 }
 
 /* Merge two pointer arrays */
-static __init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
+__init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
 {
        struct attribute **new;
        int j, i;
@@ -1748,11 +1748,22 @@ static inline void x86_pmu_read(struct perf_event *event)
  * Start group events scheduling transaction
  * Set the flag to make pmu::enable() not perform the
  * schedulability test, it will be performed at commit time
+ *
+ * We only support PERF_PMU_TXN_ADD transactions. Save the
+ * transaction flags but otherwise ignore non-PERF_PMU_TXN_ADD
+ * transactions.
  */
-static void x86_pmu_start_txn(struct pmu *pmu)
+static void x86_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags)
 {
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       WARN_ON_ONCE(cpuc->txn_flags);          /* txn already in flight */
+
+       cpuc->txn_flags = txn_flags;
+       if (txn_flags & ~PERF_PMU_TXN_ADD)
+               return;
+
        perf_pmu_disable(pmu);
-       __this_cpu_or(cpu_hw_events.group_flag, PERF_EVENT_TXN);
        __this_cpu_write(cpu_hw_events.n_txn, 0);
 }
 
@@ -1763,7 +1774,16 @@ static void x86_pmu_start_txn(struct pmu *pmu)
  */
 static void x86_pmu_cancel_txn(struct pmu *pmu)
 {
-       __this_cpu_and(cpu_hw_events.group_flag, ~PERF_EVENT_TXN);
+       unsigned int txn_flags;
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */
+
+       txn_flags = cpuc->txn_flags;
+       cpuc->txn_flags = 0;
+       if (txn_flags & ~PERF_PMU_TXN_ADD)
+               return;
+
        /*
         * Truncate collected array by the number of events added in this
         * transaction. See x86_pmu_add() and x86_pmu_*_txn().
@@ -1786,6 +1806,13 @@ static int x86_pmu_commit_txn(struct pmu *pmu)
        int assign[X86_PMC_IDX_MAX];
        int n, ret;
 
+       WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */
+
+       if (cpuc->txn_flags & ~PERF_PMU_TXN_ADD) {
+               cpuc->txn_flags = 0;
+               return 0;
+       }
+
        n = cpuc->n_events;
 
        if (!x86_pmu_initialized())
@@ -1801,7 +1828,7 @@ static int x86_pmu_commit_txn(struct pmu *pmu)
         */
        memcpy(cpuc->assign, assign, n*sizeof(int));
 
-       cpuc->group_flag &= ~PERF_EVENT_TXN;
+       cpuc->txn_flags = 0;
        perf_pmu_enable(pmu);
        return 0;
 }
@@ -2179,6 +2206,7 @@ static unsigned long get_segment_base(unsigned int segment)
        int idx = segment >> 3;
 
        if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
+#ifdef CONFIG_MODIFY_LDT_SYSCALL
                struct ldt_struct *ldt;
 
                if (idx > LDT_ENTRIES)
@@ -2190,6 +2218,9 @@ static unsigned long get_segment_base(unsigned int segment)
                        return 0;
 
                desc = &ldt->entries[idx];
+#else
+               return 0;
+#endif
        } else {
                if (idx > GDT_ENTRIES)
                        return 0;
@@ -2200,7 +2231,7 @@ static unsigned long get_segment_base(unsigned int segment)
        return get_desc_base(desc);
 }
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_IA32_EMULATION
 
 #include <asm/compat.h>