/** * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request to fill * @kbuf: the kernel buffer * @len: length of user data * @gfp_mask: memory allocation flags * * Description: * Data will be mapped directly if possible. Otherwise a bounce * buffer is used. Can be called multple times to append multple * buffers. */ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, unsigned int len, gfp_t gfp_mask) { int reading = rq_data_dir(rq) == READ; unsigned long addr = (unsigned long) kbuf; int do_copy = 0; struct bio *bio; int ret; if (len > (queue_max_hw_sectors(q) << 9)) return -EINVAL; if (!len || !kbuf) return -EINVAL; do_copy = !blk_rq_aligned(q, addr, len) || object_starts_on_stack(kbuf); if (do_copy) bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading); else bio = bio_map_kern(q, kbuf, len, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); if (rq_data_dir(rq) == WRITE) bio->bi_rw |= REQ_WRITE; if (do_copy) rq->cmd_flags |= REQ_COPY_USER; ret = blk_rq_append_bio(q, rq, bio); if (unlikely(ret)) { /* request is too big */ bio_put(bio); return ret; } blk_queue_bounce(q, &rq->bio); rq->buffer = NULL; return 0; }
/* * AArch64 PCS assigns the frame pointer to x29. * * A simple function prologue looks like this: * sub sp, sp, #0x10 * stp x29, x30, [sp] * mov x29, sp * * A simple function epilogue looks like this: * mov sp, x29 * ldp x29, x30, [sp] * add sp, sp, #0x10 */ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) { unsigned long high, low; unsigned long fp = frame->fp; unsigned long irq_stack_ptr; /* * Switching between stacks is valid when tracing current and in * non-preemptible context. */ if (tsk == current && !preemptible()) irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id()); else irq_stack_ptr = 0; low = frame->sp; /* irq stacks are not THREAD_SIZE aligned */ if (on_irq_stack(frame->sp, raw_smp_processor_id())) high = irq_stack_ptr; else high = ALIGN(low, THREAD_SIZE) - 0x20; if (fp < low || fp > high || fp & 0xf) return -EINVAL; frame->sp = fp + 0x10; frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8)); #ifdef CONFIG_FUNCTION_GRAPH_TRACER if (tsk && tsk->ret_stack && (frame->pc == (unsigned long)return_to_handler)) { /* * This is a case where function graph tracer has * modified a return address (LR) in a stack frame * to hook a function return. * So replace it to an original value. */ frame->pc = tsk->ret_stack[frame->graph--].ret; } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ /* * Check whether we are going to walk through from interrupt stack * to task stack. * If we reach the end of the stack - and its an interrupt stack, * unpack the dummy frame to find the original elr. * * Check the frame->fp we read from the bottom of the irq_stack, * and the original task stack pointer are both in current->stack. */ if (frame->sp == irq_stack_ptr) { struct pt_regs *irq_args; unsigned long orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); if (object_starts_on_stack((void *)orig_sp) && object_starts_on_stack((void *)frame->fp)) { frame->sp = orig_sp; /* orig_sp is the saved pt_regs, find the elr */ irq_args = (struct pt_regs *)orig_sp; frame->pc = irq_args->pc; } else { /* * This frame has a non-standard format, and we * didn't fix it, because the data looked wrong. * Refuse to output this frame. */ return -EINVAL; } } return 0; }