arch/um/drivers/mconsole_kern.c

Source file repositories/reference/linux-study-clean/arch/um/drivers/mconsole_kern.c

File Facts

System
Linux kernel
Corpus path
arch/um/drivers/mconsole_kern.c
Extension
.c
Size
19005 bytes
Lines
872
Domain
Architecture Layer
Bucket
arch/um
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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

struct unplugged_pages {
	struct list_head list;
	void *pages[UNPLUGGED_PER_PAGE];
};

static DEFINE_MUTEX(plug_mem_mutex);
static unsigned long long unplugged_pages_count;
static LIST_HEAD(unplugged_pages);
static int unplug_index = UNPLUGGED_PER_PAGE;

static int mem_config(char *str, char **error_out)
{
	unsigned long long diff;
	int err = -EINVAL, i, add;
	char *ret;

	if (str[0] != '=') {
		*error_out = "Expected '=' after 'mem'";
		goto out;
	}

	str++;
	if (str[0] == '-')
		add = 0;
	else if (str[0] == '+') {
		add = 1;
	}
	else {
		*error_out = "Expected increment to start with '-' or '+'";
		goto out;
	}

	str++;
	diff = memparse(str, &ret);
	if (*ret != '\0') {
		*error_out = "Failed to parse memory increment";
		goto out;
	}

	diff /= PAGE_SIZE;

	mutex_lock(&plug_mem_mutex);
	for (i = 0; i < diff; i++) {
		struct unplugged_pages *unplugged;
		void *addr;

		if (add) {
			if (list_empty(&unplugged_pages))
				break;

			unplugged = list_entry(unplugged_pages.next,
					       struct unplugged_pages, list);
			if (unplug_index > 0)
				addr = unplugged->pages[--unplug_index];
			else {
				list_del(&unplugged->list);
				addr = unplugged;
				unplug_index = UNPLUGGED_PER_PAGE;
			}

			free_page((unsigned long) addr);
			unplugged_pages_count--;
		}
		else {
			struct page *page;

			page = alloc_page(GFP_ATOMIC);
			if (page == NULL)
				break;

			unplugged = page_address(page);
			if (unplug_index == UNPLUGGED_PER_PAGE) {
				list_add(&unplugged->list, &unplugged_pages);
				unplug_index = 0;
			}
			else {
				struct list_head *entry = unplugged_pages.next;
				addr = unplugged;

				unplugged = list_entry(entry,
						       struct unplugged_pages,
						       list);
				err = os_drop_memory(addr, PAGE_SIZE);
				if (err) {
					printk(KERN_ERR "Failed to release "
					       "memory - errno = %d\n", err);
					*error_out = "Failed to release memory";
					goto out_unlock;
				}
				unplugged->pages[unplug_index++] = addr;

Annotation

Implementation Notes