arch/um/os-Linux/skas/mem.c

Source file repositories/reference/linux-study-clean/arch/um/os-Linux/skas/mem.c

File Facts

System
Linux kernel
Corpus path
arch/um/os-Linux/skas/mem.c
Extension
.c
Size
7044 bytes
Lines
285
Domain
Architecture Layer
Bucket
arch/um
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (n < 0) {
			printk(UM_KERN_ERR "Registers -\n");
			for (i = 0; i < MAX_REG_NR; i++)
				printk(UM_KERN_ERR "\t%d\t0x%lx\n", i, syscall_regs[i]);
			panic("%s : PTRACE_SETREGS failed, errno = %d\n",
			      __func__, -n);
		}

		err = ptrace(PTRACE_CONT, pid, 0, 0);
		if (err)
			panic("Failed to continue stub, pid = %d, errno = %d\n",
			      pid, errno);

		wait_stub_done(pid);
	}

	/*
	 * proc_data->err will be negative if there was an (unexpected) error.
	 * In that case, syscall_data_len points to the last executed syscall,
	 * otherwise it will be zero (but we do not need to rely on that).
	 */
	if (proc_data->err < 0) {
		syscall_stub_dump_error(mm_idp);

		/* Store error code in case someone tries to add more syscalls */
		mm_idp->syscall_data_len = proc_data->err;
	} else {
		mm_idp->syscall_data_len = 0;
	}

	if (using_seccomp)
		mm_idp->syscall_fd_num = 0;

	return mm_idp->syscall_data_len;
}

int syscall_stub_flush(struct mm_id *mm_idp)
{
	int res;

	if (mm_idp->syscall_data_len == 0)
		return 0;

	/* If an error happened already, report it and reset the state. */
	if (mm_idp->syscall_data_len < 0) {
		res = mm_idp->syscall_data_len;
		mm_idp->syscall_data_len = 0;
		return res;
	}

	res = do_syscall_stub(mm_idp);
	mm_idp->syscall_data_len = 0;

	return res;
}

struct stub_syscall *syscall_stub_alloc(struct mm_id *mm_idp)
{
	struct stub_syscall *sc;
	struct stub_data *proc_data = (struct stub_data *) mm_idp->stack;

	if (mm_idp->syscall_data_len > 0 &&
	    mm_idp->syscall_data_len == ARRAY_SIZE(proc_data->syscall_data))
		do_syscall_stub(mm_idp);

	if (mm_idp->syscall_data_len < 0) {
		/* Return dummy to retain error state. */
		sc = &proc_data->syscall_data[0];
	} else {
		sc = &proc_data->syscall_data[mm_idp->syscall_data_len];
		mm_idp->syscall_data_len += 1;
	}
	memset(sc, 0, sizeof(*sc));

	return sc;
}

static struct stub_syscall *syscall_stub_get_previous(struct mm_id *mm_idp,
						      int syscall_type,
						      unsigned long virt)
{
	if (mm_idp->syscall_data_len > 0) {
		struct stub_data *proc_data = (void *) mm_idp->stack;
		struct stub_syscall *sc;

		sc = &proc_data->syscall_data[mm_idp->syscall_data_len - 1];

		if (sc->syscall == syscall_type &&
		    sc->mem.addr + sc->mem.length == virt)
			return sc;

Annotation

Implementation Notes