arch/s390/mm/maccess.c

Source file repositories/reference/linux-study-clean/arch/s390/mm/maccess.c

File Facts

System
Linux kernel
Corpus path
arch/s390/mm/maccess.c
Extension
.c
Size
4754 bytes
Lines
195
Domain
Architecture Layer
Bucket
arch/s390
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 (pte_val(pte) != pte_val(*memcpy_real_ptep)) {
			__ptep_ipte(__memcpy_real_area, memcpy_real_ptep, 0, 0, IPTE_GLOBAL);
			set_pte(memcpy_real_ptep, pte);
		}
		copied = copy_to_iter(chunk, len, iter);
		mutex_unlock(&memcpy_real_mutex);

		count -= copied;
		src += copied;
		res += copied;
		if (copied < len)
			break;
	}
	return res;
}

int memcpy_real(void *dest, unsigned long src, size_t count)
{
	struct iov_iter iter;
	struct kvec kvec;

	kvec.iov_base = dest;
	kvec.iov_len = count;
	iov_iter_kvec(&iter, ITER_DEST, &kvec, 1, count);
	if (memcpy_real_iter(&iter, src, count) < count)
		return -EFAULT;
	return 0;
}

/*
 * Find CPU that owns swapped prefix page
 */
static int get_swapped_owner(phys_addr_t addr)
{
	phys_addr_t lc;
	int cpu;

	for_each_online_cpu(cpu) {
		lc = virt_to_phys(lowcore_ptr[cpu]);
		if (addr > lc + sizeof(struct lowcore) - 1 || addr < lc)
			continue;
		return cpu;
	}
	return -1;
}

/*
 * Convert a physical pointer for /dev/mem access
 *
 * For swapped prefix pages a new buffer is returned that contains a copy of
 * the absolute memory. The buffer size is maximum one page large.
 */
void *xlate_dev_mem_ptr(phys_addr_t addr)
{
	void *ptr = phys_to_virt(addr);
	void *bounce = ptr;
	struct lowcore *abs_lc;
	unsigned long size;
	int this_cpu, cpu;

	cpus_read_lock();
	this_cpu = get_cpu();
	if (addr >= sizeof(struct lowcore)) {
		cpu = get_swapped_owner(addr);
		if (cpu < 0)
			goto out;
	}
	bounce = (void *)__get_free_page(GFP_ATOMIC);
	if (!bounce)
		goto out;
	size = PAGE_SIZE - (addr & ~PAGE_MASK);
	if (addr < sizeof(struct lowcore)) {
		abs_lc = get_abs_lowcore();
		ptr = (void *)abs_lc + addr;
		memcpy(bounce, ptr, size);
		put_abs_lowcore(abs_lc);
	} else if (cpu == this_cpu) {
		ptr = (void *)(addr - virt_to_phys(lowcore_ptr[cpu]));
		memcpy(bounce, ptr, size);
	} else {
		memcpy(bounce, ptr, size);
	}
out:
	put_cpu();
	cpus_read_unlock();
	return bounce;
}

/*
 * Free converted buffer for /dev/mem access (if necessary)

Annotation

Implementation Notes