topa
struct topa *topa;
list_for_each_entry(topa, &buf->tables, list) {
if (topa->offset + topa->size > (unsigned long)pg << PAGE_SHIFT)
if (WARN_ON_ONCE(topa->last == -1))
tp = topa_to_page(topa);
cur_pg = PFN_DOWN(topa->offset);
if (topa->z_count) {
z_pg = TOPA_ENTRY_PAGES(topa, 0) * (topa->z_count + 1);
start_idx = topa->z_count + 1;
idx = (pg - cur_pg) / TOPA_ENTRY_PAGES(topa, 0);
for (idx = start_idx, cur_pg += z_pg; idx < topa->last; idx++) {
if (cur_pg + TOPA_ENTRY_PAGES(topa, idx) > pg)
cur_pg += TOPA_ENTRY_PAGES(topa, idx);
struct topa *topa;
topa = &tp->topa;
if (topa == buf->first)
topa = buf->last;
topa = list_prev_entry(topa, list);
tp = topa_to_page(topa);
return &tp->table[topa->last - 1];
buf->cur = &cur_tp->topa;
struct topa *topa, *iter;
list_for_each_entry_safe(topa, iter, &buf->tables, list) {
topa_free(topa);
struct topa *topa;
topa = topa_alloc(cpu, gfp);
if (!topa)
topa_insert_table(buf, topa);
BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE);
((PAGE_SIZE - sizeof(struct topa)) / sizeof(struct topa_entry))
struct topa topa;
static inline struct topa_page *topa_to_page(struct topa *topa)
return container_of(topa, struct topa_page, topa);
static inline phys_addr_t topa_pfn(struct topa *topa)
return PFN_DOWN(virt_to_phys(topa_to_page(topa)));
static struct topa *topa_alloc(int cpu, gfp_t gfp)
tp->topa.last = 0;
TOPA_ENTRY(&tp->topa, 1)->base = page_to_phys(p) >> TOPA_SHIFT;
TOPA_ENTRY(&tp->topa, 1)->end = 1;
return &tp->topa;
static void topa_free(struct topa *topa)
free_page((unsigned long)topa);
static void topa_insert_table(struct pt_buffer *buf, struct topa *topa)
struct topa *last = buf->last;
list_add_tail(&topa->list, &buf->tables);
buf->first = buf->last = buf->cur = topa;
topa->offset = last->offset + last->size;
buf->last = topa;
TOPA_ENTRY(last, -1)->base = topa_pfn(topa);
static bool topa_table_full(struct topa *topa)
return !!topa->last;
return topa->last == TENTS_PER_PAGE - 1;
struct topa *topa = buf->last;
if (topa_table_full(topa)) {
topa = topa_alloc(cpu, gfp);
if (!topa)
topa_insert_table(buf, topa);
if (topa->z_count == topa->last - 1) {
if (order == TOPA_ENTRY(topa, topa->last - 1)->size)
topa->z_count++;
TOPA_ENTRY(topa, -1)->base = page_to_phys(p) >> TOPA_SHIFT;
TOPA_ENTRY(topa, -1)->size = order;
TOPA_ENTRY(topa, -1)->intr = 1;
TOPA_ENTRY(topa, -1)->stop = 1;
topa->last++;
topa->size += sizes(order);
struct topa *topa;
list_for_each_entry(topa, &buf->tables, list) {
struct topa_page *tp = topa_to_page(topa);
topa->offset, topa->size);
if (!i && topa->z_count)
i += topa->z_count;
buf->cur = list_entry(buf->cur->list.next, struct topa,
buf->cur = &tp->topa;
struct topa *first, *last, *cur;