Lines Matching +full:inactive +full:-
1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (c) 2013-2014, Intel Corporation.
86 int cpu = event->cpu; in bts_buffer_setup_aux()
87 int node = (cpu == -1) ? cpu : cpu_to_node(cpu); in bts_buffer_setup_aux()
109 bb->nr_pages = nr_pages; in bts_buffer_setup_aux()
110 bb->nr_bufs = nr_buf; in bts_buffer_setup_aux()
111 bb->snapshot = overwrite; in bts_buffer_setup_aux()
112 bb->data_pages = pages; in bts_buffer_setup_aux()
113 bb->real_size = size - size % BTS_RECORD_SIZE; in bts_buffer_setup_aux()
115 for (pg = 0, nr_buf = 0, offset = 0, pad = 0; nr_buf < bb->nr_bufs; nr_buf++) { in bts_buffer_setup_aux()
120 bb->buf[nr_buf].page = page; in bts_buffer_setup_aux()
121 bb->buf[nr_buf].offset = offset; in bts_buffer_setup_aux()
122 bb->buf[nr_buf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0); in bts_buffer_setup_aux()
123 bb->buf[nr_buf].size = buf_size(page) - bb->buf[nr_buf].displacement; in bts_buffer_setup_aux()
124 pad = bb->buf[nr_buf].size % BTS_RECORD_SIZE; in bts_buffer_setup_aux()
125 bb->buf[nr_buf].size -= pad; in bts_buffer_setup_aux()
141 return bb->buf[idx].offset + bb->buf[idx].displacement; in bts_buffer_offset()
149 struct bts_phys *phys = &bb->buf[bb->cur_buf]; in bts_config_buffer()
150 unsigned long index, thresh = 0, end = phys->size; in bts_config_buffer()
151 struct page *page = phys->page; in bts_config_buffer()
153 index = local_read(&bb->head); in bts_config_buffer()
155 if (!bb->snapshot) { in bts_config_buffer()
156 if (bb->end < phys->offset + buf_size(page)) in bts_config_buffer()
157 end = bb->end - phys->offset - phys->displacement; in bts_config_buffer()
159 index -= phys->offset + phys->displacement; in bts_config_buffer()
161 if (end - index > BTS_SAFETY_MARGIN) in bts_config_buffer()
162 thresh = end - BTS_SAFETY_MARGIN; in bts_config_buffer()
163 else if (end - index > BTS_RECORD_SIZE) in bts_config_buffer()
164 thresh = end - BTS_RECORD_SIZE; in bts_config_buffer()
169 ds->bts_buffer_base = (u64)(long)page_address(page) + phys->displacement; in bts_config_buffer()
170 ds->bts_index = ds->bts_buffer_base + index; in bts_config_buffer()
171 ds->bts_absolute_maximum = ds->bts_buffer_base + end; in bts_config_buffer()
172 ds->bts_interrupt_threshold = !bb->snapshot in bts_config_buffer()
173 ? ds->bts_buffer_base + thresh in bts_config_buffer()
174 : ds->bts_absolute_maximum + BTS_RECORD_SIZE; in bts_config_buffer()
179 unsigned long index = head - phys->offset; in bts_buffer_pad_out()
181 memset(page_address(phys->page) + index, 0, phys->size - index); in bts_buffer_pad_out()
188 struct bts_buffer *bb = perf_get_aux(&bts->handle); in bts_update()
189 unsigned long index = ds->bts_index - ds->bts_buffer_base, old, head; in bts_update()
194 head = index + bts_buffer_offset(bb, bb->cur_buf); in bts_update()
195 old = local_xchg(&bb->head, head); in bts_update()
197 if (!bb->snapshot) { in bts_update()
201 if (ds->bts_index >= ds->bts_absolute_maximum) in bts_update()
202 perf_aux_output_flag(&bts->handle, in bts_update()
209 local_add(head - old, &bb->data_size); in bts_update()
211 local_set(&bb->data_size, head); in bts_update()
227 * - is set when bts::handle::event is valid, that is, between
229 * - is zero otherwise;
230 * - is ordered against bts::handle::event with a compiler barrier.
236 struct bts_buffer *bb = perf_get_aux(&bts->handle); in __bts_event_start()
239 if (!bb->snapshot) in __bts_event_start()
241 if (!event->attr.exclude_kernel) in __bts_event_start()
243 if (!event->attr.exclude_user) in __bts_event_start()
254 /* INACTIVE/STOPPED -> ACTIVE */ in __bts_event_start()
255 WRITE_ONCE(bts->state, BTS_STATE_ACTIVE); in __bts_event_start()
267 bb = perf_aux_output_begin(&bts->handle, event); in bts_event_start()
271 if (bts_buffer_reset(bb, &bts->handle)) in bts_event_start()
274 bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base; in bts_event_start()
275 bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum; in bts_event_start()
276 bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold; in bts_event_start()
279 event->hw.state = 0; in bts_event_start()
286 perf_aux_output_end(&bts->handle, 0); in bts_event_start()
289 event->hw.state = PERF_HES_STOPPED; in bts_event_start()
296 /* ACTIVE -> INACTIVE(PMI)/STOPPED(->stop()) */ in __bts_event_stop()
297 WRITE_ONCE(bts->state, state); in __bts_event_stop()
311 int state = READ_ONCE(bts->state); in bts_event_stop()
317 bb = perf_get_aux(&bts->handle); in bts_event_stop()
319 event->hw.state |= PERF_HES_STOPPED; in bts_event_stop()
325 if (bb->snapshot) in bts_event_stop()
326 bts->handle.head = in bts_event_stop()
327 local_xchg(&bb->data_size, in bts_event_stop()
328 bb->nr_pages << PAGE_SHIFT); in bts_event_stop()
329 perf_aux_output_end(&bts->handle, in bts_event_stop()
330 local_xchg(&bb->data_size, 0)); in bts_event_stop()
333 cpuc->ds->bts_index = bts->ds_back.bts_buffer_base; in bts_event_stop()
334 cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base; in bts_event_stop()
335 cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum; in bts_event_stop()
336 cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold; in bts_event_stop()
349 state = READ_ONCE(bts->state); in intel_bts_enable_local()
351 * Here we transition from INACTIVE to ACTIVE; in intel_bts_enable_local()
361 if (bts->handle.event) in intel_bts_enable_local()
362 __bts_event_start(bts->handle.event); in intel_bts_enable_local()
375 * Here we transition from ACTIVE to INACTIVE; in intel_bts_disable_local()
376 * do nothing for STOPPED or INACTIVE. in intel_bts_disable_local()
378 if (READ_ONCE(bts->state) != BTS_STATE_ACTIVE) in intel_bts_disable_local()
381 if (bts->handle.event) in intel_bts_disable_local()
382 __bts_event_stop(bts->handle.event, BTS_STATE_INACTIVE); in intel_bts_disable_local()
393 if (bb->snapshot) in bts_buffer_reset()
396 head = handle->head & ((bb->nr_pages << PAGE_SHIFT) - 1); in bts_buffer_reset()
398 phys = &bb->buf[bb->cur_buf]; in bts_buffer_reset()
399 space = phys->offset + phys->displacement + phys->size - head; in bts_buffer_reset()
401 if (space > handle->size) { in bts_buffer_reset()
402 space = handle->size; in bts_buffer_reset()
403 space -= space % BTS_RECORD_SIZE; in bts_buffer_reset()
407 next_buf = bb->cur_buf + 1; in bts_buffer_reset()
408 if (next_buf >= bb->nr_bufs) in bts_buffer_reset()
410 next_phys = &bb->buf[next_buf]; in bts_buffer_reset()
411 gap = buf_size(phys->page) - phys->displacement - phys->size + in bts_buffer_reset()
412 next_phys->displacement; in bts_buffer_reset()
414 if (handle->size >= skip) { in bts_buffer_reset()
415 next_space = next_phys->size; in bts_buffer_reset()
416 if (next_space + skip > handle->size) { in bts_buffer_reset()
417 next_space = handle->size - skip; in bts_buffer_reset()
418 next_space -= next_space % BTS_RECORD_SIZE; in bts_buffer_reset()
429 head = phys->offset + phys->displacement; in bts_buffer_reset()
435 bb->cur_buf = next_buf; in bts_buffer_reset()
436 local_set(&bb->head, head); in bts_buffer_reset()
442 wakeup = BTS_SAFETY_MARGIN + BTS_RECORD_SIZE + handle->wakeup - in bts_buffer_reset()
443 handle->head; in bts_buffer_reset()
446 space -= space % BTS_RECORD_SIZE; in bts_buffer_reset()
449 bb->end = head + space; in bts_buffer_reset()
453 * we hit absolute_maximum - see bts_update() in bts_buffer_reset()
456 return -ENOSPC; in bts_buffer_reset()
463 struct debug_store *ds = this_cpu_ptr(&cpu_hw_events)->ds; in intel_bts_interrupt()
468 int err = -ENOSPC, handled = 0; in intel_bts_interrupt()
474 event = bts->handle.event; in intel_bts_interrupt()
479 if (ds && (ds->bts_index >= ds->bts_interrupt_threshold)) in intel_bts_interrupt()
484 * so we can only be INACTIVE or STOPPED in intel_bts_interrupt()
486 if (READ_ONCE(bts->state) == BTS_STATE_STOPPED) in intel_bts_interrupt()
489 bb = perf_get_aux(&bts->handle); in intel_bts_interrupt()
498 if (bb->snapshot) in intel_bts_interrupt()
501 old_head = local_read(&bb->head); in intel_bts_interrupt()
505 if (old_head == local_read(&bb->head)) in intel_bts_interrupt()
508 perf_aux_output_end(&bts->handle, local_xchg(&bb->data_size, 0)); in intel_bts_interrupt()
510 bb = perf_aux_output_begin(&bts->handle, event); in intel_bts_interrupt()
512 err = bts_buffer_reset(bb, &bts->handle); in intel_bts_interrupt()
515 WRITE_ONCE(bts->state, BTS_STATE_STOPPED); in intel_bts_interrupt()
523 perf_aux_output_end(&bts->handle, 0); in intel_bts_interrupt()
539 struct hw_perf_event *hwc = &event->hw; in bts_event_add()
541 event->hw.state = PERF_HES_STOPPED; in bts_event_add()
543 if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask)) in bts_event_add()
544 return -EBUSY; in bts_event_add()
546 if (bts->handle.event) in bts_event_add()
547 return -EBUSY; in bts_event_add()
551 if (hwc->state & PERF_HES_STOPPED) in bts_event_add()
552 return -EINVAL; in bts_event_add()
568 if (event->attr.type != bts_pmu.type) in bts_event_init()
569 return -ENOENT; in bts_event_init()
575 * to the user in a zero-copy fashion. in bts_event_init()
577 if (event->attr.exclude_kernel) { in bts_event_init()
584 return -EBUSY; in bts_event_init()
592 event->destroy = bts_event_destroy; in bts_event_init()
604 return -ENODEV; in bts_init()
608 return -ENODEV; in bts_init()
616 * However, since this driver supports per-CPU and per-task inherit in bts_init()
625 return -ENODEV; in bts_init()
630 return -ENOMEM; in bts_init()
644 return perf_pmu_register(&bts_pmu, "intel_bts", -1); in bts_init()