···66 tristate "OProfile system profiling (EXPERIMENTAL)"77 depends on PROFILING88 depends on HAVE_OPROFILE99+ select TRACING1010+ select RING_BUFFER911 help1012 OProfile is a profiling system capable of profiling the1113 whole system, include the kernel, kernel modules, libraries,
+90-132
arch/x86/oprofile/op_model_amd.c
···22 * @file op_model_amd.c33 * athlon / K7 / K8 / Family 10h model-specific MSR operations44 *55- * @remark Copyright 2002-2008 OProfile authors55+ * @remark Copyright 2002-2009 OProfile authors66 * @remark Read the file COPYING77 *88 * @author John Levon···1010 * @author Graydon Hoare1111 * @author Robert Richter <robert.richter@amd.com>1212 * @author Barry Kasindorf1313-*/1313+ */14141515#include <linux/oprofile.h>1616#include <linux/device.h>···6060#define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */6161#define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */62626363-/* Codes used in cpu_buffer.c */6464-/* This produces duplicate code, need to be fixed */6565-#define IBS_FETCH_BEGIN 36666-#define IBS_OP_BEGIN 46363+#define IBS_FETCH_SIZE 66464+#define IBS_OP_SIZE 1267656868-/* The function interface needs to be fixed, something like add6969- data. Should then be added to linux/oprofile.h. */7070-extern void7171-oprofile_add_ibs_sample(struct pt_regs *const regs,7272- unsigned int *const ibs_sample, int ibs_code);7373-7474-struct ibs_fetch_sample {7575- /* MSRC001_1031 IBS Fetch Linear Address Register */7676- unsigned int ibs_fetch_lin_addr_low;7777- unsigned int ibs_fetch_lin_addr_high;7878- /* MSRC001_1030 IBS Fetch Control Register */7979- unsigned int ibs_fetch_ctl_low;8080- unsigned int ibs_fetch_ctl_high;8181- /* MSRC001_1032 IBS Fetch Physical Address Register */8282- unsigned int ibs_fetch_phys_addr_low;8383- unsigned int ibs_fetch_phys_addr_high;8484-};8585-8686-struct ibs_op_sample {8787- /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */8888- unsigned int ibs_op_rip_low;8989- unsigned int ibs_op_rip_high;9090- /* MSRC001_1035 IBS Op Data Register */9191- unsigned int ibs_op_data1_low;9292- unsigned int ibs_op_data1_high;9393- /* MSRC001_1036 IBS Op Data 2 Register */9494- unsigned int ibs_op_data2_low;9595- unsigned int ibs_op_data2_high;9696- /* MSRC001_1037 IBS Op Data 3 Register */9797- unsigned int ibs_op_data3_low;9898- unsigned int ibs_op_data3_high;9999- /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */100100- unsigned int ibs_dc_linear_low;101101- unsigned int ibs_dc_linear_high;102102- /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */103103- unsigned int ibs_dc_phys_low;104104- unsigned int ibs_dc_phys_high;105105-};106106-107107-/*108108- * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+109109-*/110110-static void clear_ibs_nmi(void);111111-112112-static int ibs_allowed; /* AMD Family10h and later */6666+static int has_ibs; /* AMD Family10h and later */1136711468struct op_ibs_config {11569 unsigned long op_enabled;···154200op_amd_handle_ibs(struct pt_regs * const regs,155201 struct op_msrs const * const msrs)156202{157157- unsigned int low, high;158158- struct ibs_fetch_sample ibs_fetch;159159- struct ibs_op_sample ibs_op;203203+ u32 low, high;204204+ u64 msr;205205+ struct op_entry entry;160206161161- if (!ibs_allowed)207207+ if (!has_ibs)162208 return 1;163209164210 if (ibs_config.fetch_enabled) {165211 rdmsr(MSR_AMD64_IBSFETCHCTL, low, high);166212 if (high & IBS_FETCH_HIGH_VALID_BIT) {167167- ibs_fetch.ibs_fetch_ctl_high = high;168168- ibs_fetch.ibs_fetch_ctl_low = low;169169- rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high);170170- ibs_fetch.ibs_fetch_lin_addr_high = high;171171- ibs_fetch.ibs_fetch_lin_addr_low = low;172172- rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high);173173- ibs_fetch.ibs_fetch_phys_addr_high = high;174174- ibs_fetch.ibs_fetch_phys_addr_low = low;213213+ rdmsrl(MSR_AMD64_IBSFETCHLINAD, msr);214214+ oprofile_write_reserve(&entry, regs, msr,215215+ IBS_FETCH_CODE, IBS_FETCH_SIZE);216216+ oprofile_add_data(&entry, (u32)msr);217217+ oprofile_add_data(&entry, (u32)(msr >> 32));218218+ oprofile_add_data(&entry, low);219219+ oprofile_add_data(&entry, high);220220+ rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, msr);221221+ oprofile_add_data(&entry, (u32)msr);222222+ oprofile_add_data(&entry, (u32)(msr >> 32));223223+ oprofile_write_commit(&entry);175224176176- oprofile_add_ibs_sample(regs,177177- (unsigned int *)&ibs_fetch,178178- IBS_FETCH_BEGIN);179179-180180- /*reenable the IRQ */181181- rdmsr(MSR_AMD64_IBSFETCHCTL, low, high);225225+ /* reenable the IRQ */182226 high &= ~IBS_FETCH_HIGH_VALID_BIT;183227 high |= IBS_FETCH_HIGH_ENABLE;184228 low &= IBS_FETCH_LOW_MAX_CNT_MASK;···187235 if (ibs_config.op_enabled) {188236 rdmsr(MSR_AMD64_IBSOPCTL, low, high);189237 if (low & IBS_OP_LOW_VALID_BIT) {190190- rdmsr(MSR_AMD64_IBSOPRIP, low, high);191191- ibs_op.ibs_op_rip_low = low;192192- ibs_op.ibs_op_rip_high = high;193193- rdmsr(MSR_AMD64_IBSOPDATA, low, high);194194- ibs_op.ibs_op_data1_low = low;195195- ibs_op.ibs_op_data1_high = high;196196- rdmsr(MSR_AMD64_IBSOPDATA2, low, high);197197- ibs_op.ibs_op_data2_low = low;198198- ibs_op.ibs_op_data2_high = high;199199- rdmsr(MSR_AMD64_IBSOPDATA3, low, high);200200- ibs_op.ibs_op_data3_low = low;201201- ibs_op.ibs_op_data3_high = high;202202- rdmsr(MSR_AMD64_IBSDCLINAD, low, high);203203- ibs_op.ibs_dc_linear_low = low;204204- ibs_op.ibs_dc_linear_high = high;205205- rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high);206206- ibs_op.ibs_dc_phys_low = low;207207- ibs_op.ibs_dc_phys_high = high;238238+ rdmsrl(MSR_AMD64_IBSOPRIP, msr);239239+ oprofile_write_reserve(&entry, regs, msr,240240+ IBS_OP_CODE, IBS_OP_SIZE);241241+ oprofile_add_data(&entry, (u32)msr);242242+ oprofile_add_data(&entry, (u32)(msr >> 32));243243+ rdmsrl(MSR_AMD64_IBSOPDATA, msr);244244+ oprofile_add_data(&entry, (u32)msr);245245+ oprofile_add_data(&entry, (u32)(msr >> 32));246246+ rdmsrl(MSR_AMD64_IBSOPDATA2, msr);247247+ oprofile_add_data(&entry, (u32)msr);248248+ oprofile_add_data(&entry, (u32)(msr >> 32));249249+ rdmsrl(MSR_AMD64_IBSOPDATA3, msr);250250+ oprofile_add_data(&entry, (u32)msr);251251+ oprofile_add_data(&entry, (u32)(msr >> 32));252252+ rdmsrl(MSR_AMD64_IBSDCLINAD, msr);253253+ oprofile_add_data(&entry, (u32)msr);254254+ oprofile_add_data(&entry, (u32)(msr >> 32));255255+ rdmsrl(MSR_AMD64_IBSDCPHYSAD, msr);256256+ oprofile_add_data(&entry, (u32)msr);257257+ oprofile_add_data(&entry, (u32)(msr >> 32));258258+ oprofile_write_commit(&entry);208259209260 /* reenable the IRQ */210210- oprofile_add_ibs_sample(regs,211211- (unsigned int *)&ibs_op,212212- IBS_OP_BEGIN);213213- rdmsr(MSR_AMD64_IBSOPCTL, low, high);214261 high = 0;215262 low &= ~IBS_OP_LOW_VALID_BIT;216263 low |= IBS_OP_LOW_ENABLE;···259308 }260309261310#ifdef CONFIG_OPROFILE_IBS262262- if (ibs_allowed && ibs_config.fetch_enabled) {311311+ if (has_ibs && ibs_config.fetch_enabled) {263312 low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF;264313 high = ((ibs_config.rand_en & 0x1) << 25) /* bit 57 */265314 + IBS_FETCH_HIGH_ENABLE;266315 wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);267316 }268317269269- if (ibs_allowed && ibs_config.op_enabled) {318318+ if (has_ibs && ibs_config.op_enabled) {270319 low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF)271320 + ((ibs_config.dispatched_ops & 0x1) << 19) /* bit 19 */272321 + IBS_OP_LOW_ENABLE;···282331 unsigned int low, high;283332 int i;284333285285- /* Subtle: stop on all counters to avoid race with286286- * setting our pm callback */334334+ /*335335+ * Subtle: stop on all counters to avoid race with setting our336336+ * pm callback337337+ */287338 for (i = 0 ; i < NUM_COUNTERS ; ++i) {288339 if (!reset_value[i])289340 continue;···295342 }296343297344#ifdef CONFIG_OPROFILE_IBS298298- if (ibs_allowed && ibs_config.fetch_enabled) {299299- low = 0; /* clear max count and enable */345345+ if (has_ibs && ibs_config.fetch_enabled) {346346+ /* clear max count and enable */347347+ low = 0;300348 high = 0;301349 wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);302350 }303351304304- if (ibs_allowed && ibs_config.op_enabled) {305305- low = 0; /* clear max count and enable */352352+ if (has_ibs && ibs_config.op_enabled) {353353+ /* clear max count and enable */354354+ low = 0;306355 high = 0;307356 wrmsr(MSR_AMD64_IBSOPCTL, low, high);308357 }···325370 }326371}327372328328-#ifndef CONFIG_OPROFILE_IBS329329-330330-/* no IBS support */331331-332332-static int op_amd_init(struct oprofile_operations *ops)333333-{334334- return 0;335335-}336336-337337-static void op_amd_exit(void) {}338338-339339-#else373373+#ifdef CONFIG_OPROFILE_IBS340374341375static u8 ibs_eilvt_off;342376···339395 setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);340396}341397342342-static int pfm_amd64_setup_eilvt(void)398398+static int init_ibs_nmi(void)343399{344400#define IBSCTL_LVTOFFSETVAL (1 << 8)345401#define IBSCTL 0x1cc···363419 | IBSCTL_LVTOFFSETVAL);364420 pci_read_config_dword(cpu_cfg, IBSCTL, &value);365421 if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {422422+ pci_dev_put(cpu_cfg);366423 printk(KERN_DEBUG "Failed to setup IBS LVT offset, "367424 "IBSCTL = 0x%08x", value);368425 return 1;···388443 return 0;389444}390445391391-/*392392- * initialize the APIC for the IBS interrupts393393- * if available (AMD Family10h rev B0 and later)394394- */395395-static void setup_ibs(void)446446+/* uninitialize the APIC for the IBS interrupts if needed */447447+static void clear_ibs_nmi(void)396448{397397- ibs_allowed = boot_cpu_has(X86_FEATURE_IBS);449449+ if (has_ibs)450450+ on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);451451+}398452399399- if (!ibs_allowed)453453+/* initialize the APIC for the IBS interrupts if available */454454+static void ibs_init(void)455455+{456456+ has_ibs = boot_cpu_has(X86_FEATURE_IBS);457457+458458+ if (!has_ibs)400459 return;401460402402- if (pfm_amd64_setup_eilvt()) {403403- ibs_allowed = 0;461461+ if (init_ibs_nmi()) {462462+ has_ibs = 0;404463 return;405464 }406465407466 printk(KERN_INFO "oprofile: AMD IBS detected\n");408467}409468410410-411411-/*412412- * unitialize the APIC for the IBS interrupts if needed on AMD Family10h413413- * rev B0 and later */414414-static void clear_ibs_nmi(void)469469+static void ibs_exit(void)415470{416416- if (ibs_allowed)417417- on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);471471+ if (!has_ibs)472472+ return;473473+474474+ clear_ibs_nmi();418475}419476420477static int (*create_arch_files)(struct super_block *sb, struct dentry *root);···433486 if (ret)434487 return ret;435488436436- if (!ibs_allowed)489489+ if (!has_ibs)437490 return ret;438491439492 /* model specific files */···466519467520static int op_amd_init(struct oprofile_operations *ops)468521{469469- setup_ibs();522522+ ibs_init();470523 create_arch_files = ops->create_files;471524 ops->create_files = setup_ibs_files;472525 return 0;···474527475528static void op_amd_exit(void)476529{477477- clear_ibs_nmi();530530+ ibs_exit();478531}479532480480-#endif533533+#else534534+535535+/* no IBS support */536536+537537+static int op_amd_init(struct oprofile_operations *ops)538538+{539539+ return 0;540540+}541541+542542+static void op_amd_exit(void) {}543543+544544+#endif /* CONFIG_OPROFILE_IBS */481545482546struct op_x86_model_spec const op_amd_spec = {483547 .init = op_amd_init,
+82-149
drivers/oprofile/buffer_sync.c
···11/**22 * @file buffer_sync.c33 *44- * @remark Copyright 2002 OProfile authors44+ * @remark Copyright 2002-2009 OProfile authors55 * @remark Read the file COPYING66 *77 * @author John Levon <levon@movementarian.org>88 * @author Barry Kasindorf99+ * @author Robert Richter <robert.richter@amd.com>910 *1011 * This is the core of the buffer management. Each1112 * CPU buffer is processed and entered into the···269268 return cookie;270269}271270272272-static void increment_tail(struct oprofile_cpu_buffer *b)273273-{274274- unsigned long new_tail = b->tail_pos + 1;275275-276276- rmb(); /* be sure fifo pointers are synchromized */277277-278278- if (new_tail < b->buffer_size)279279- b->tail_pos = new_tail;280280- else281281- b->tail_pos = 0;282282-}283283-284271static unsigned long last_cookie = INVALID_COOKIE;285272286273static void add_cpu_switch(int i)···316327 add_event_entry(TRACE_BEGIN_CODE);317328}318329319319-#ifdef CONFIG_OPROFILE_IBS320320-321321-#define IBS_FETCH_CODE_SIZE 2322322-#define IBS_OP_CODE_SIZE 5323323-#define IBS_EIP(offset) \324324- (((struct op_sample *)&cpu_buf->buffer[(offset)])->eip)325325-#define IBS_EVENT(offset) \326326- (((struct op_sample *)&cpu_buf->buffer[(offset)])->event)327327-328328-/*329329- * Add IBS fetch and op entries to event buffer330330- */331331-static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code,332332- struct mm_struct *mm)330330+static void add_data(struct op_entry *entry, struct mm_struct *mm)333331{334334- unsigned long rip;335335- int i, count;336336- unsigned long ibs_cookie = 0;332332+ unsigned long code, pc, val;333333+ unsigned long cookie;337334 off_t offset;338335339339- increment_tail(cpu_buf); /* move to RIP entry */340340-341341- rip = IBS_EIP(cpu_buf->tail_pos);342342-343343-#ifdef __LP64__344344- rip += IBS_EVENT(cpu_buf->tail_pos) << 32;345345-#endif336336+ if (!op_cpu_buffer_get_data(entry, &code))337337+ return;338338+ if (!op_cpu_buffer_get_data(entry, &pc))339339+ return;340340+ if (!op_cpu_buffer_get_size(entry))341341+ return;346342347343 if (mm) {348348- ibs_cookie = lookup_dcookie(mm, rip, &offset);344344+ cookie = lookup_dcookie(mm, pc, &offset);349345350350- if (ibs_cookie == NO_COOKIE)351351- offset = rip;352352- if (ibs_cookie == INVALID_COOKIE) {346346+ if (cookie == NO_COOKIE)347347+ offset = pc;348348+ if (cookie == INVALID_COOKIE) {353349 atomic_inc(&oprofile_stats.sample_lost_no_mapping);354354- offset = rip;350350+ offset = pc;355351 }356356- if (ibs_cookie != last_cookie) {357357- add_cookie_switch(ibs_cookie);358358- last_cookie = ibs_cookie;352352+ if (cookie != last_cookie) {353353+ add_cookie_switch(cookie);354354+ last_cookie = cookie;359355 }360356 } else361361- offset = rip;357357+ offset = pc;362358363359 add_event_entry(ESCAPE_CODE);364360 add_event_entry(code);365361 add_event_entry(offset); /* Offset from Dcookie */366362367367- /* we send the Dcookie offset, but send the raw Linear Add also*/368368- add_event_entry(IBS_EIP(cpu_buf->tail_pos));369369- add_event_entry(IBS_EVENT(cpu_buf->tail_pos));370370-371371- if (code == IBS_FETCH_CODE)372372- count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/373373- else374374- count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/375375-376376- for (i = 0; i < count; i++) {377377- increment_tail(cpu_buf);378378- add_event_entry(IBS_EIP(cpu_buf->tail_pos));379379- add_event_entry(IBS_EVENT(cpu_buf->tail_pos));380380- }363363+ while (op_cpu_buffer_get_data(entry, &val))364364+ add_event_entry(val);381365}382366383383-#endif384384-385385-static void add_sample_entry(unsigned long offset, unsigned long event)367367+static inline void add_sample_entry(unsigned long offset, unsigned long event)386368{387369 add_event_entry(offset);388370 add_event_entry(event);389371}390372391373392392-static int add_us_sample(struct mm_struct *mm, struct op_sample *s)374374+/*375375+ * Add a sample to the global event buffer. If possible the376376+ * sample is converted into a persistent dentry/offset pair377377+ * for later lookup from userspace. Return 0 on failure.378378+ */379379+static int380380+add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel)393381{394382 unsigned long cookie;395383 off_t offset;384384+385385+ if (in_kernel) {386386+ add_sample_entry(s->eip, s->event);387387+ return 1;388388+ }389389+390390+ /* add userspace sample */391391+392392+ if (!mm) {393393+ atomic_inc(&oprofile_stats.sample_lost_no_mm);394394+ return 0;395395+ }396396397397 cookie = lookup_dcookie(mm, s->eip, &offset);398398···398420 add_sample_entry(offset, s->event);399421400422 return 1;401401-}402402-403403-404404-/* Add a sample to the global event buffer. If possible the405405- * sample is converted into a persistent dentry/offset pair406406- * for later lookup from userspace.407407- */408408-static int409409-add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel)410410-{411411- if (in_kernel) {412412- add_sample_entry(s->eip, s->event);413413- return 1;414414- } else if (mm) {415415- return add_us_sample(mm, s);416416- } else {417417- atomic_inc(&oprofile_stats.sample_lost_no_mm);418418- }419419- return 0;420423}421424422425···422463static inline int is_code(unsigned long val)423464{424465 return val == ESCAPE_CODE;425425-}426426-427427-428428-/* "acquire" as many cpu buffer slots as we can */429429-static unsigned long get_slots(struct oprofile_cpu_buffer *b)430430-{431431- unsigned long head = b->head_pos;432432- unsigned long tail = b->tail_pos;433433-434434- /*435435- * Subtle. This resets the persistent last_task436436- * and in_kernel values used for switching notes.437437- * BUT, there is a small window between reading438438- * head_pos, and this call, that means samples439439- * can appear at the new head position, but not440440- * be prefixed with the notes for switching441441- * kernel mode or a task switch. This small hole442442- * can lead to mis-attribution or samples where443443- * we don't know if it's in the kernel or not,444444- * at the start of an event buffer.445445- */446446- cpu_buffer_reset(b);447447-448448- if (head >= tail)449449- return head - tail;450450-451451- return head + (b->buffer_size - tail);452466}453467454468···491559 */492560void sync_buffer(int cpu)493561{494494- struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);495562 struct mm_struct *mm = NULL;563563+ struct mm_struct *oldmm;564564+ unsigned long val;496565 struct task_struct *new;497566 unsigned long cookie = 0;498567 int in_kernel = 1;499568 sync_buffer_state state = sb_buffer_start;500500-#ifndef CONFIG_OPROFILE_IBS501569 unsigned int i;502570 unsigned long available;503503-#endif571571+ unsigned long flags;572572+ struct op_entry entry;573573+ struct op_sample *sample;504574505575 mutex_lock(&buffer_mutex);506576507577 add_cpu_switch(cpu);508578509509- /* Remember, only we can modify tail_pos */510510-511511-#ifndef CONFIG_OPROFILE_IBS512512- available = get_slots(cpu_buf);579579+ op_cpu_buffer_reset(cpu);580580+ available = op_cpu_buffer_entries(cpu);513581514582 for (i = 0; i < available; ++i) {515515-#else516516- while (get_slots(cpu_buf)) {517517-#endif518518- struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos];583583+ sample = op_cpu_buffer_read_entry(&entry, cpu);584584+ if (!sample)585585+ break;519586520520- if (is_code(s->eip)) {521521- if (s->event <= CPU_IS_KERNEL) {522522- /* kernel/userspace switch */523523- in_kernel = s->event;524524- if (state == sb_buffer_start)525525- state = sb_sample_start;526526- add_kernel_ctx_switch(s->event);527527- } else if (s->event == CPU_TRACE_BEGIN) {587587+ if (is_code(sample->eip)) {588588+ flags = sample->event;589589+ if (flags & TRACE_BEGIN) {528590 state = sb_bt_start;529591 add_trace_begin();530530-#ifdef CONFIG_OPROFILE_IBS531531- } else if (s->event == IBS_FETCH_BEGIN) {532532- state = sb_bt_start;533533- add_ibs_begin(cpu_buf, IBS_FETCH_CODE, mm);534534- } else if (s->event == IBS_OP_BEGIN) {535535- state = sb_bt_start;536536- add_ibs_begin(cpu_buf, IBS_OP_CODE, mm);537537-#endif538538- } else {539539- struct mm_struct *oldmm = mm;540540-592592+ }593593+ if (flags & KERNEL_CTX_SWITCH) {594594+ /* kernel/userspace switch */595595+ in_kernel = flags & IS_KERNEL;596596+ if (state == sb_buffer_start)597597+ state = sb_sample_start;598598+ add_kernel_ctx_switch(flags & IS_KERNEL);599599+ }600600+ if (flags & USER_CTX_SWITCH601601+ && op_cpu_buffer_get_data(&entry, &val)) {541602 /* userspace context switch */542542- new = (struct task_struct *)s->event;543543-603603+ new = (struct task_struct *)val;604604+ oldmm = mm;544605 release_mm(oldmm);545606 mm = take_tasks_mm(new);546607 if (mm != oldmm)547608 cookie = get_exec_dcookie(mm);548609 add_user_ctx_switch(new, cookie);549610 }550550- } else if (state >= sb_bt_start &&551551- !add_sample(mm, s, in_kernel)) {552552- if (state == sb_bt_start) {553553- state = sb_bt_ignore;554554- atomic_inc(&oprofile_stats.bt_lost_no_mapping);555555- }611611+ if (op_cpu_buffer_get_size(&entry))612612+ add_data(&entry, mm);613613+ continue;556614 }557615558558- increment_tail(cpu_buf);616616+ if (state < sb_bt_start)617617+ /* ignore sample */618618+ continue;619619+620620+ if (add_sample(mm, sample, in_kernel))621621+ continue;622622+623623+ /* ignore backtraces if failed to add a sample */624624+ if (state == sb_bt_start) {625625+ state = sb_bt_ignore;626626+ atomic_inc(&oprofile_stats.bt_lost_no_mapping);627627+ }559628 }560629 release_mm(mm);561630
+249-162
drivers/oprofile/cpu_buffer.c
···11/**22 * @file cpu_buffer.c33 *44- * @remark Copyright 2002 OProfile authors44+ * @remark Copyright 2002-2009 OProfile authors55 * @remark Read the file COPYING66 *77 * @author John Levon <levon@movementarian.org>88 * @author Barry Kasindorf <barry.kasindorf@amd.com>99+ * @author Robert Richter <robert.richter@amd.com>910 *1011 * Each CPU has a local buffer that stores PC value/event1112 * pairs. We also log context switches when we notice them.···2928#include "buffer_sync.h"3029#include "oprof.h"31303131+#define OP_BUFFER_FLAGS 03232+3333+/*3434+ * Read and write access is using spin locking. Thus, writing to the3535+ * buffer by NMI handler (x86) could occur also during critical3636+ * sections when reading the buffer. To avoid this, there are 23737+ * buffers for independent read and write access. Read access is in3838+ * process context only, write access only in the NMI handler. If the3939+ * read buffer runs empty, both buffers are swapped atomically. There4040+ * is potentially a small window during swapping where the buffers are4141+ * disabled and samples could be lost.4242+ *4343+ * Using 2 buffers is a little bit overhead, but the solution is clear4444+ * and does not require changes in the ring buffer implementation. It4545+ * can be changed to a single buffer solution when the ring buffer4646+ * access is implemented as non-locking atomic code.4747+ */4848+static struct ring_buffer *op_ring_buffer_read;4949+static struct ring_buffer *op_ring_buffer_write;3250DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);33513452static void wq_sync_buffer(struct work_struct *work);···5535#define DEFAULT_TIMER_EXPIRE (HZ / 10)5636static int work_enabled;57375858-void free_cpu_buffers(void)5959-{6060- int i;6161-6262- for_each_possible_cpu(i) {6363- vfree(per_cpu(cpu_buffer, i).buffer);6464- per_cpu(cpu_buffer, i).buffer = NULL;6565- }6666-}6767-6838unsigned long oprofile_get_cpu_buffer_size(void)6939{7070- return fs_cpu_buffer_size;4040+ return oprofile_cpu_buffer_size;7141}72427343void oprofile_cpu_buffer_inc_smpl_lost(void)···6858 cpu_buf->sample_lost_overflow++;6959}70606161+void free_cpu_buffers(void)6262+{6363+ if (op_ring_buffer_read)6464+ ring_buffer_free(op_ring_buffer_read);6565+ op_ring_buffer_read = NULL;6666+ if (op_ring_buffer_write)6767+ ring_buffer_free(op_ring_buffer_write);6868+ op_ring_buffer_write = NULL;6969+}7070+7171int alloc_cpu_buffers(void)7272{7373 int i;74747575- unsigned long buffer_size = fs_cpu_buffer_size;7575+ unsigned long buffer_size = oprofile_cpu_buffer_size;7676+7777+ op_ring_buffer_read = ring_buffer_alloc(buffer_size, OP_BUFFER_FLAGS);7878+ if (!op_ring_buffer_read)7979+ goto fail;8080+ op_ring_buffer_write = ring_buffer_alloc(buffer_size, OP_BUFFER_FLAGS);8181+ if (!op_ring_buffer_write)8282+ goto fail;76837784 for_each_possible_cpu(i) {7885 struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);7979-8080- b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size,8181- cpu_to_node(i));8282- if (!b->buffer)8383- goto fail;84868587 b->last_task = NULL;8688 b->last_is_kernel = -1;8789 b->tracing = 0;8890 b->buffer_size = buffer_size;8989- b->tail_pos = 0;9090- b->head_pos = 0;9191 b->sample_received = 0;9292 b->sample_lost_overflow = 0;9393 b->backtrace_aborted = 0;···144124 flush_scheduled_work();145125}146126147147-/* Resets the cpu buffer to a sane state. */148148-void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf)127127+/*128128+ * This function prepares the cpu buffer to write a sample.129129+ *130130+ * Struct op_entry is used during operations on the ring buffer while131131+ * struct op_sample contains the data that is stored in the ring132132+ * buffer. Struct entry can be uninitialized. The function reserves a133133+ * data array that is specified by size. Use134134+ * op_cpu_buffer_write_commit() after preparing the sample. In case of135135+ * errors a null pointer is returned, otherwise the pointer to the136136+ * sample.137137+ *138138+ */139139+struct op_sample140140+*op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size)149141{150150- /* reset these to invalid values; the next sample151151- * collected will populate the buffer with proper152152- * values to initialize the buffer153153- */154154- cpu_buf->last_is_kernel = -1;155155- cpu_buf->last_task = NULL;156156-}157157-158158-/* compute number of available slots in cpu_buffer queue */159159-static unsigned long nr_available_slots(struct oprofile_cpu_buffer const *b)160160-{161161- unsigned long head = b->head_pos;162162- unsigned long tail = b->tail_pos;163163-164164- if (tail > head)165165- return (tail - head) - 1;166166-167167- return tail + (b->buffer_size - head) - 1;168168-}169169-170170-static void increment_head(struct oprofile_cpu_buffer *b)171171-{172172- unsigned long new_head = b->head_pos + 1;173173-174174- /* Ensure anything written to the slot before we175175- * increment is visible */176176- wmb();177177-178178- if (new_head < b->buffer_size)179179- b->head_pos = new_head;142142+ entry->event = ring_buffer_lock_reserve143143+ (op_ring_buffer_write, sizeof(struct op_sample) +144144+ size * sizeof(entry->sample->data[0]), &entry->irq_flags);145145+ if (entry->event)146146+ entry->sample = ring_buffer_event_data(entry->event);180147 else181181- b->head_pos = 0;148148+ entry->sample = NULL;149149+150150+ if (!entry->sample)151151+ return NULL;152152+153153+ entry->size = size;154154+ entry->data = entry->sample->data;155155+156156+ return entry->sample;182157}183158184184-static inline void185185-add_sample(struct oprofile_cpu_buffer *cpu_buf,186186- unsigned long pc, unsigned long event)159159+int op_cpu_buffer_write_commit(struct op_entry *entry)187160{188188- struct op_sample *entry = &cpu_buf->buffer[cpu_buf->head_pos];189189- entry->eip = pc;190190- entry->event = event;191191- increment_head(cpu_buf);161161+ return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event,162162+ entry->irq_flags);192163}193164194194-static inline void195195-add_code(struct oprofile_cpu_buffer *buffer, unsigned long value)165165+struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu)196166{197197- add_sample(buffer, ESCAPE_CODE, value);167167+ struct ring_buffer_event *e;168168+ e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);169169+ if (e)170170+ goto event;171171+ if (ring_buffer_swap_cpu(op_ring_buffer_read,172172+ op_ring_buffer_write,173173+ cpu))174174+ return NULL;175175+ e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);176176+ if (e)177177+ goto event;178178+ return NULL;179179+180180+event:181181+ entry->event = e;182182+ entry->sample = ring_buffer_event_data(e);183183+ entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample))184184+ / sizeof(entry->sample->data[0]);185185+ entry->data = entry->sample->data;186186+ return entry->sample;198187}199188200200-/* This must be safe from any context. It's safe writing here201201- * because of the head/tail separation of the writer and reader202202- * of the CPU buffer.189189+unsigned long op_cpu_buffer_entries(int cpu)190190+{191191+ return ring_buffer_entries_cpu(op_ring_buffer_read, cpu)192192+ + ring_buffer_entries_cpu(op_ring_buffer_write, cpu);193193+}194194+195195+static int196196+op_add_code(struct oprofile_cpu_buffer *cpu_buf, unsigned long backtrace,197197+ int is_kernel, struct task_struct *task)198198+{199199+ struct op_entry entry;200200+ struct op_sample *sample;201201+ unsigned long flags;202202+ int size;203203+204204+ flags = 0;205205+206206+ if (backtrace)207207+ flags |= TRACE_BEGIN;208208+209209+ /* notice a switch from user->kernel or vice versa */210210+ is_kernel = !!is_kernel;211211+ if (cpu_buf->last_is_kernel != is_kernel) {212212+ cpu_buf->last_is_kernel = is_kernel;213213+ flags |= KERNEL_CTX_SWITCH;214214+ if (is_kernel)215215+ flags |= IS_KERNEL;216216+ }217217+218218+ /* notice a task switch */219219+ if (cpu_buf->last_task != task) {220220+ cpu_buf->last_task = task;221221+ flags |= USER_CTX_SWITCH;222222+ }223223+224224+ if (!flags)225225+ /* nothing to do */226226+ return 0;227227+228228+ if (flags & USER_CTX_SWITCH)229229+ size = 1;230230+ else231231+ size = 0;232232+233233+ sample = op_cpu_buffer_write_reserve(&entry, size);234234+ if (!sample)235235+ return -ENOMEM;236236+237237+ sample->eip = ESCAPE_CODE;238238+ sample->event = flags;239239+240240+ if (size)241241+ op_cpu_buffer_add_data(&entry, (unsigned long)task);242242+243243+ op_cpu_buffer_write_commit(&entry);244244+245245+ return 0;246246+}247247+248248+static inline int249249+op_add_sample(struct oprofile_cpu_buffer *cpu_buf,250250+ unsigned long pc, unsigned long event)251251+{252252+ struct op_entry entry;253253+ struct op_sample *sample;254254+255255+ sample = op_cpu_buffer_write_reserve(&entry, 0);256256+ if (!sample)257257+ return -ENOMEM;258258+259259+ sample->eip = pc;260260+ sample->event = event;261261+262262+ return op_cpu_buffer_write_commit(&entry);263263+}264264+265265+/*266266+ * This must be safe from any context.203267 *204268 * is_kernel is needed because on some architectures you cannot205269 * tell if you are in kernel or user space simply by looking at206270 * pc. We tag this in the buffer by generating kernel enter/exit207271 * events whenever is_kernel changes208272 */209209-static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,210210- int is_kernel, unsigned long event)273273+static int274274+log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,275275+ unsigned long backtrace, int is_kernel, unsigned long event)211276{212212- struct task_struct *task;213213-214277 cpu_buf->sample_received++;215278216279 if (pc == ESCAPE_CODE) {···301198 return 0;302199 }303200304304- if (nr_available_slots(cpu_buf) < 3) {305305- cpu_buf->sample_lost_overflow++;306306- return 0;307307- }201201+ if (op_add_code(cpu_buf, backtrace, is_kernel, current))202202+ goto fail;308203309309- is_kernel = !!is_kernel;204204+ if (op_add_sample(cpu_buf, pc, event))205205+ goto fail;310206311311- task = current;312312-313313- /* notice a switch from user->kernel or vice versa */314314- if (cpu_buf->last_is_kernel != is_kernel) {315315- cpu_buf->last_is_kernel = is_kernel;316316- add_code(cpu_buf, is_kernel);317317- }318318-319319- /* notice a task switch */320320- if (cpu_buf->last_task != task) {321321- cpu_buf->last_task = task;322322- add_code(cpu_buf, (unsigned long)task);323323- }324324-325325- add_sample(cpu_buf, pc, event);326207 return 1;208208+209209+fail:210210+ cpu_buf->sample_lost_overflow++;211211+ return 0;327212}328213329329-static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf)214214+static inline void oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf)330215{331331- if (nr_available_slots(cpu_buf) < 4) {332332- cpu_buf->sample_lost_overflow++;333333- return 0;334334- }335335-336336- add_code(cpu_buf, CPU_TRACE_BEGIN);337216 cpu_buf->tracing = 1;338338- return 1;339217}340218341341-static void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf)219219+static inline void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf)342220{343221 cpu_buf->tracing = 0;344222}345223346346-void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,347347- unsigned long event, int is_kernel)224224+static inline void225225+__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,226226+ unsigned long event, int is_kernel)348227{349228 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);229229+ unsigned long backtrace = oprofile_backtrace_depth;350230351351- if (!backtrace_depth) {352352- log_sample(cpu_buf, pc, is_kernel, event);231231+ /*232232+ * if log_sample() fail we can't backtrace since we lost the233233+ * source of this event234234+ */235235+ if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event))236236+ /* failed */353237 return;354354- }355238356356- if (!oprofile_begin_trace(cpu_buf))239239+ if (!backtrace)357240 return;358241359359- /* if log_sample() fail we can't backtrace since we lost the source360360- * of this event */361361- if (log_sample(cpu_buf, pc, is_kernel, event))362362- oprofile_ops.backtrace(regs, backtrace_depth);242242+ oprofile_begin_trace(cpu_buf);243243+ oprofile_ops.backtrace(regs, backtrace);363244 oprofile_end_trace(cpu_buf);245245+}246246+247247+void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,248248+ unsigned long event, int is_kernel)249249+{250250+ __oprofile_add_ext_sample(pc, regs, event, is_kernel);364251}365252366253void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)···358265 int is_kernel = !user_mode(regs);359266 unsigned long pc = profile_pc(regs);360267361361- oprofile_add_ext_sample(pc, regs, event, is_kernel);268268+ __oprofile_add_ext_sample(pc, regs, event, is_kernel);362269}363270364364-#ifdef CONFIG_OPROFILE_IBS365365-366366-#define MAX_IBS_SAMPLE_SIZE 14367367-368368-void oprofile_add_ibs_sample(struct pt_regs *const regs,369369- unsigned int *const ibs_sample, int ibs_code)271271+/*272272+ * Add samples with data to the ring buffer.273273+ *274274+ * Use oprofile_add_data(&entry, val) to add data and275275+ * oprofile_write_commit(&entry) to commit the sample.276276+ */277277+void278278+oprofile_write_reserve(struct op_entry *entry, struct pt_regs * const regs,279279+ unsigned long pc, int code, int size)370280{281281+ struct op_sample *sample;371282 int is_kernel = !user_mode(regs);372283 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);373373- struct task_struct *task;374284375285 cpu_buf->sample_received++;376286377377- if (nr_available_slots(cpu_buf) < MAX_IBS_SAMPLE_SIZE) {378378- /* we can't backtrace since we lost the source of this event */379379- cpu_buf->sample_lost_overflow++;380380- return;381381- }287287+ /* no backtraces for samples with data */288288+ if (op_add_code(cpu_buf, 0, is_kernel, current))289289+ goto fail;382290383383- /* notice a switch from user->kernel or vice versa */384384- if (cpu_buf->last_is_kernel != is_kernel) {385385- cpu_buf->last_is_kernel = is_kernel;386386- add_code(cpu_buf, is_kernel);387387- }291291+ sample = op_cpu_buffer_write_reserve(entry, size + 2);292292+ if (!sample)293293+ goto fail;294294+ sample->eip = ESCAPE_CODE;295295+ sample->event = 0; /* no flags */388296389389- /* notice a task switch */390390- if (!is_kernel) {391391- task = current;392392- if (cpu_buf->last_task != task) {393393- cpu_buf->last_task = task;394394- add_code(cpu_buf, (unsigned long)task);395395- }396396- }297297+ op_cpu_buffer_add_data(entry, code);298298+ op_cpu_buffer_add_data(entry, pc);397299398398- add_code(cpu_buf, ibs_code);399399- add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]);400400- add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]);401401- add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]);300300+ return;402301403403- if (ibs_code == IBS_OP_BEGIN) {404404- add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]);405405- add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]);406406- add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]);407407- }408408-409409- if (backtrace_depth)410410- oprofile_ops.backtrace(regs, backtrace_depth);302302+fail:303303+ cpu_buf->sample_lost_overflow++;411304}412305413413-#endif306306+int oprofile_add_data(struct op_entry *entry, unsigned long val)307307+{308308+ return op_cpu_buffer_add_data(entry, val);309309+}310310+311311+int oprofile_write_commit(struct op_entry *entry)312312+{313313+ return op_cpu_buffer_write_commit(entry);314314+}414315415316void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)416317{417318 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);418418- log_sample(cpu_buf, pc, is_kernel, event);319319+ log_sample(cpu_buf, pc, 0, is_kernel, event);419320}420321421322void oprofile_add_trace(unsigned long pc)···419332 if (!cpu_buf->tracing)420333 return;421334422422- if (nr_available_slots(cpu_buf) < 1) {423423- cpu_buf->tracing = 0;424424- cpu_buf->sample_lost_overflow++;425425- return;426426- }335335+ /*336336+ * broken frame can give an eip with the same value as an337337+ * escape code, abort the trace if we get it338338+ */339339+ if (pc == ESCAPE_CODE)340340+ goto fail;427341428428- /* broken frame can give an eip with the same value as an escape code,429429- * abort the trace if we get it */430430- if (pc == ESCAPE_CODE) {431431- cpu_buf->tracing = 0;432432- cpu_buf->backtrace_aborted++;433433- return;434434- }342342+ if (op_add_sample(cpu_buf, pc, 0))343343+ goto fail;435344436436- add_sample(cpu_buf, pc, 0);345345+ return;346346+fail:347347+ cpu_buf->tracing = 0;348348+ cpu_buf->backtrace_aborted++;349349+ return;437350}438351439352/*
+62-10
drivers/oprofile/cpu_buffer.h
···11/**22 * @file cpu_buffer.h33 *44- * @remark Copyright 2002 OProfile authors44+ * @remark Copyright 2002-2009 OProfile authors55 * @remark Read the file COPYING66 *77 * @author John Levon <levon@movementarian.org>88+ * @author Robert Richter <robert.richter@amd.com>89 */9101011#ifndef OPROFILE_CPU_BUFFER_H···1615#include <linux/workqueue.h>1716#include <linux/cache.h>1817#include <linux/sched.h>1818+#include <linux/ring_buffer.h>19192020struct task_struct;2121···3230struct op_sample {3331 unsigned long eip;3432 unsigned long event;3333+ unsigned long data[0];3534};36353636+struct op_entry;3737+3738struct oprofile_cpu_buffer {3838- volatile unsigned long head_pos;3939- volatile unsigned long tail_pos;4039 unsigned long buffer_size;4140 struct task_struct *last_task;4241 int last_is_kernel;4342 int tracing;4444- struct op_sample *buffer;4543 unsigned long sample_received;4644 unsigned long sample_lost_overflow;4745 unsigned long backtrace_aborted;···52505351DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);54525555-void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf);5353+/*5454+ * Resets the cpu buffer to a sane state.5555+ *5656+ * reset these to invalid values; the next sample collected will5757+ * populate the buffer with proper values to initialize the buffer5858+ */5959+static inline void op_cpu_buffer_reset(int cpu)6060+{6161+ struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);56625757-/* transient events for the CPU buffer -> event buffer */5858-#define CPU_IS_KERNEL 15959-#define CPU_TRACE_BEGIN 26060-#define IBS_FETCH_BEGIN 36161-#define IBS_OP_BEGIN 46363+ cpu_buf->last_is_kernel = -1;6464+ cpu_buf->last_task = NULL;6565+}6666+6767+struct op_sample6868+*op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size);6969+int op_cpu_buffer_write_commit(struct op_entry *entry);7070+struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu);7171+unsigned long op_cpu_buffer_entries(int cpu);7272+7373+/* returns the remaining free size of data in the entry */7474+static inline7575+int op_cpu_buffer_add_data(struct op_entry *entry, unsigned long val)7676+{7777+ if (!entry->size)7878+ return 0;7979+ *entry->data = val;8080+ entry->size--;8181+ entry->data++;8282+ return entry->size;8383+}8484+8585+/* returns the size of data in the entry */8686+static inline8787+int op_cpu_buffer_get_size(struct op_entry *entry)8888+{8989+ return entry->size;9090+}9191+9292+/* returns 0 if empty or the size of data including the current value */9393+static inline9494+int op_cpu_buffer_get_data(struct op_entry *entry, unsigned long *val)9595+{9696+ int size = entry->size;9797+ if (!size)9898+ return 0;9999+ *val = *entry->data;100100+ entry->size--;101101+ entry->data++;102102+ return size;103103+}104104+105105+/* extra data flags */106106+#define KERNEL_CTX_SWITCH (1UL << 0)107107+#define IS_KERNEL (1UL << 1)108108+#define TRACE_BEGIN (1UL << 2)109109+#define USER_CTX_SWITCH (1UL << 3)6211063111#endif /* OPROFILE_CPU_BUFFER_H */
···2323struct oprofile_operations oprofile_ops;24242525unsigned long oprofile_started;2626-unsigned long backtrace_depth;2626+unsigned long oprofile_backtrace_depth;2727static unsigned long is_setup;2828static DEFINE_MUTEX(start_mutex);2929···172172 goto out;173173 }174174175175- backtrace_depth = val;175175+ oprofile_backtrace_depth = val;176176177177out:178178 mutex_unlock(&start_mutex);
+4-4
drivers/oprofile/oprof.h
···21212222struct oprofile_operations;23232424-extern unsigned long fs_buffer_size;2525-extern unsigned long fs_cpu_buffer_size;2626-extern unsigned long fs_buffer_watershed;2424+extern unsigned long oprofile_buffer_size;2525+extern unsigned long oprofile_cpu_buffer_size;2626+extern unsigned long oprofile_buffer_watershed;2727extern struct oprofile_operations oprofile_ops;2828extern unsigned long oprofile_started;2929-extern unsigned long backtrace_depth;2929+extern unsigned long oprofile_backtrace_depth;30303131struct super_block;3232struct dentry;
···8686void oprofile_arch_exit(void);87878888/**8989- * Add a sample. This may be called from any context. Pass9090- * smp_processor_id() as cpu.8989+ * Add a sample. This may be called from any context.9190 */9291void oprofile_add_sample(struct pt_regs * const regs, unsigned long event);9392···164165unsigned long oprofile_get_cpu_buffer_size(void);165166void oprofile_cpu_buffer_inc_smpl_lost(void);166167168168+/* cpu buffer functions */169169+170170+struct op_sample;171171+172172+struct op_entry {173173+ struct ring_buffer_event *event;174174+ struct op_sample *sample;175175+ unsigned long irq_flags;176176+ unsigned long size;177177+ unsigned long *data;178178+};179179+180180+void oprofile_write_reserve(struct op_entry *entry,181181+ struct pt_regs * const regs,182182+ unsigned long pc, int code, int size);183183+int oprofile_add_data(struct op_entry *entry, unsigned long val);184184+int oprofile_write_commit(struct op_entry *entry);185185+167186#endif /* OPROFILE_H */
+2
include/linux/ring_buffer.h
···116116117117unsigned long ring_buffer_entries(struct ring_buffer *buffer);118118unsigned long ring_buffer_overruns(struct ring_buffer *buffer);119119+unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu);120120+unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu);119121120122u64 ring_buffer_time_stamp(int cpu);121123void ring_buffer_normalize_time_stamp(int cpu, u64 *ts);
+42-2
kernel/trace/ring_buffer.c
···3131{3232 ring_buffers_off = 0;3333}3434+EXPORT_SYMBOL_GPL(tracing_on);34353536/**3637 * tracing_off - turn off all tracing buffers···4544{4645 ring_buffers_off = 1;4746}4747+EXPORT_SYMBOL_GPL(tracing_off);48484949/* Up this if you want to test the TIME_EXTENTS and normalization */5050#define DEBUG_SHIFT 0···62606361 return time;6462}6363+EXPORT_SYMBOL_GPL(ring_buffer_time_stamp);65646665void ring_buffer_normalize_time_stamp(int cpu, u64 *ts)6766{6867 /* Just stupid testing the normalize function and deltas */6968 *ts >>= DEBUG_SHIFT;7069}7070+EXPORT_SYMBOL_GPL(ring_buffer_normalize_time_stamp);71717272#define RB_EVNT_HDR_SIZE (sizeof(struct ring_buffer_event))7373#define RB_ALIGNMENT_SHIFT 2···117113 */118114unsigned ring_buffer_event_length(struct ring_buffer_event *event)119115{120120- return rb_event_length(event);116116+ unsigned length = rb_event_length(event);117117+ if (event->type != RINGBUF_TYPE_DATA)118118+ return length;119119+ length -= RB_EVNT_HDR_SIZE;120120+ if (length > RB_MAX_SMALL_DATA + sizeof(event->array[0]))121121+ length -= sizeof(event->array[0]);122122+ return length;121123}124124+EXPORT_SYMBOL_GPL(ring_buffer_event_length);122125123126/* inline for ring buffer fast paths */124127static inline void *···147136{148137 return rb_event_data(event);149138}139139+EXPORT_SYMBOL_GPL(ring_buffer_event_data);150140151141#define for_each_buffer_cpu(buffer, cpu) \152142 for_each_cpu_mask(cpu, buffer->cpumask)···393381394382/**395383 * ring_buffer_alloc - allocate a new ring_buffer396396- * @size: the size in bytes that is needed.384384+ * @size: the size in bytes per cpu that is needed.397385 * @flags: attributes to set for the ring buffer.398386 *399387 * Currently the only flag that is available is the RB_FL_OVERWRITE···456444 kfree(buffer);457445 return NULL;458446}447447+EXPORT_SYMBOL_GPL(ring_buffer_alloc);459448460449/**461450 * ring_buffer_free - free a ring buffer.···472459473460 kfree(buffer);474461}462462+EXPORT_SYMBOL_GPL(ring_buffer_free);475463476464static void rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer);477465···634620 mutex_unlock(&buffer->mutex);635621 return -ENOMEM;636622}623623+EXPORT_SYMBOL_GPL(ring_buffer_resize);637624638625static inline int rb_null_event(struct ring_buffer_event *event)639626{···12351220 preempt_enable_notrace();12361221 return NULL;12371222}12231223+EXPORT_SYMBOL_GPL(ring_buffer_lock_reserve);1238122412391225static void rb_commit(struct ring_buffer_per_cpu *cpu_buffer,12401226 struct ring_buffer_event *event)···1285126912861270 return 0;12871271}12721272+EXPORT_SYMBOL_GPL(ring_buffer_unlock_commit);1288127312891274/**12901275 * ring_buffer_write - write data to the buffer without reserving···1351133413521335 return ret;13531336}13371337+EXPORT_SYMBOL_GPL(ring_buffer_write);1354133813551339static inline int rb_per_cpu_empty(struct ring_buffer_per_cpu *cpu_buffer)13561340{···13781360{13791361 atomic_inc(&buffer->record_disabled);13801362}13631363+EXPORT_SYMBOL_GPL(ring_buffer_record_disable);1381136413821365/**13831366 * ring_buffer_record_enable - enable writes to the buffer···13911372{13921373 atomic_dec(&buffer->record_disabled);13931374}13751375+EXPORT_SYMBOL_GPL(ring_buffer_record_enable);1394137613951377/**13961378 * ring_buffer_record_disable_cpu - stop all writes into the cpu_buffer···14131393 cpu_buffer = buffer->buffers[cpu];14141394 atomic_inc(&cpu_buffer->record_disabled);14151395}13961396+EXPORT_SYMBOL_GPL(ring_buffer_record_disable_cpu);1416139714171398/**14181399 * ring_buffer_record_enable_cpu - enable writes to the buffer···14331412 cpu_buffer = buffer->buffers[cpu];14341413 atomic_dec(&cpu_buffer->record_disabled);14351414}14151415+EXPORT_SYMBOL_GPL(ring_buffer_record_enable_cpu);1436141614371417/**14381418 * ring_buffer_entries_cpu - get the number of entries in a cpu buffer···14501428 cpu_buffer = buffer->buffers[cpu];14511429 return cpu_buffer->entries;14521430}14311431+EXPORT_SYMBOL_GPL(ring_buffer_entries_cpu);1453143214541433/**14551434 * ring_buffer_overrun_cpu - get the number of overruns in a cpu_buffer···14671444 cpu_buffer = buffer->buffers[cpu];14681445 return cpu_buffer->overrun;14691446}14471447+EXPORT_SYMBOL_GPL(ring_buffer_overrun_cpu);1470144814711449/**14721450 * ring_buffer_entries - get the number of entries in a buffer···1490146614911467 return entries;14921468}14691469+EXPORT_SYMBOL_GPL(ring_buffer_entries);1493147014941471/**14951472 * ring_buffer_overrun_cpu - get the number of overruns in buffer···1513148815141489 return overruns;15151490}14911491+EXPORT_SYMBOL_GPL(ring_buffer_overruns);1516149215171493/**15181494 * ring_buffer_iter_reset - reset an iterator···15391513 else15401514 iter->read_stamp = iter->head_page->time_stamp;15411515}15161516+EXPORT_SYMBOL_GPL(ring_buffer_iter_reset);1542151715431518/**15441519 * ring_buffer_iter_empty - check if an iterator has no more to read···15541527 return iter->head_page == cpu_buffer->commit_page &&15551528 iter->head == rb_commit_index(cpu_buffer);15561529}15301530+EXPORT_SYMBOL_GPL(ring_buffer_iter_empty);1557153115581532static void15591533rb_update_read_stamp(struct ring_buffer_per_cpu *cpu_buffer,···1825179718261798 return NULL;18271799}18001800+EXPORT_SYMBOL_GPL(ring_buffer_peek);1828180118291802/**18301803 * ring_buffer_iter_peek - peek at the next event to be read···1896186718971868 return NULL;18981869}18701870+EXPORT_SYMBOL_GPL(ring_buffer_iter_peek);1899187119001872/**19011873 * ring_buffer_consume - return an event and consume it···1924189419251895 return event;19261896}18971897+EXPORT_SYMBOL_GPL(ring_buffer_consume);1927189819281899/**19291900 * ring_buffer_read_start - start a non consuming read of the buffer···1965193419661935 return iter;19671936}19371937+EXPORT_SYMBOL_GPL(ring_buffer_read_start);1968193819691939/**19701940 * ring_buffer_finish - finish reading the iterator of the buffer···19821950 atomic_dec(&cpu_buffer->record_disabled);19831951 kfree(iter);19841952}19531953+EXPORT_SYMBOL_GPL(ring_buffer_read_finish);1985195419861955/**19871956 * ring_buffer_read - read the next item in the ring buffer by the iterator···2004197120051972 return event;20061973}19741974+EXPORT_SYMBOL_GPL(ring_buffer_read);2007197520081976/**20091977 * ring_buffer_size - return the size of the ring buffer (in bytes)···20141980{20151981 return BUF_PAGE_SIZE * buffer->pages;20161982}19831983+EXPORT_SYMBOL_GPL(ring_buffer_size);2017198420181985static void20191986rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)···2057202220582023 spin_unlock_irqrestore(&cpu_buffer->lock, flags);20592024}20252025+EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu);2060202620612027/**20622028 * ring_buffer_reset - reset a ring buffer···20702034 for_each_buffer_cpu(buffer, cpu)20712035 ring_buffer_reset_cpu(buffer, cpu);20722036}20372037+EXPORT_SYMBOL_GPL(ring_buffer_reset);2073203820742039/**20752040 * rind_buffer_empty - is the ring buffer empty?···20892052 }20902053 return 1;20912054}20552055+EXPORT_SYMBOL_GPL(ring_buffer_empty);2092205620932057/**20942058 * ring_buffer_empty_cpu - is a cpu buffer of a ring buffer empty?···21062068 cpu_buffer = buffer->buffers[cpu];21072069 return rb_per_cpu_empty(cpu_buffer);21082070}20712071+EXPORT_SYMBOL_GPL(ring_buffer_empty_cpu);2109207221102073/**21112074 * ring_buffer_swap_cpu - swap a CPU buffer between two ring buffers···2156211721572118 return 0;21582119}21202120+EXPORT_SYMBOL_GPL(ring_buffer_swap_cpu);2159212121602122static ssize_t21612123rb_simple_read(struct file *filp, char __user *ubuf,
+2-2
kernel/trace/trace.c
···914914 TRACE_FILE_LAT_FMT = 1,915915};916916917917-static void trace_iterator_increment(struct trace_iterator *iter, int cpu)917917+static void trace_iterator_increment(struct trace_iterator *iter)918918{919919 /* Don't allow ftrace to trace into the ring buffers */920920 ftrace_disable_cpu();···993993 iter->ent = __find_next_entry(iter, &iter->cpu, &iter->ts);994994995995 if (iter->ent)996996- trace_iterator_increment(iter, iter->cpu);996996+ trace_iterator_increment(iter);997997998998 return iter->ent ? iter : NULL;999999}