⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 portal.c

📁 pebble
💻 C
📖 第 1 页 / 共 3 页
字号:
	char *template, uint c, int (*entry)())
{
	PortalStack stack_type = STACK_SHARED;
	PortalSave stack_save = SAVE_FULL;	/* to make GCC happy */
	int asid_reg, const_reg, thread_reg, window_reg, bad_vaddr_reg;
	uchar window_type = '\0';
	int i, portal_len, const_offset, c_reg;
	char *s;
	Portal *portal_table;
	Port_Info *info;

	DIAG(PORTAL_DIAG,
		("new_portal: install_asid=%d id=%d server_asid=%d save=%p\n",
		install_asid, id, server_asid, save));
	DIAG(PORTAL_DIAG, ("template=%s c=%08x entry=%p\n",
		template, c, entry));

	if (template == NULL || param_check(template, NAMELEN, 1) < 0)
		error(INVALID_PORTAL_TEMPLATE);

	if (entry == NULL)
		error(INVALID_ENTRY);

	if ((save[S_TLBHI] & TLBHI_PIDMASK) != server_asid)
		error(INVALID_FRAME_CONTENTS);

	portal_table = portals[install_asid].virt;
	info = portals[install_asid].info;

	if (portal_table == NULL || info == NULL)
		error(INTERNAL_ERROR_PORTALS);

	switch(tolower(template[0])) {
	case 'e':
		stack_type = STACK_EXCEPTION;
		if (id < 0 || id >= NEXCPT)
			error(INVALID_PORTAL_NUMBER);
		if (portal_table[NPORTALS+id] != bad_excpt)
			error(PORTAL_DEFINED);
		id += NPORTALS;
		break;

	case 'q':
		stack_type = STACK_QUEUE;
		/* fall through */

	case 's':
		/* default stack type is STACK_SHARED */
		/* must not overwrite portal #0, which must point to */
		/* the undefined portal handler */
		if (id == 0)
			error(INVALID_PORTAL_NUMBER);
		if (id < 0) {
			id = sys_portal_alloc(install_asid, 1, 0);
			/* no need to check return code here, */
			/* since sys_portal_alloc fails via error() */

			/* fix owner, since we may install portal in an */
			/* unrelated domain. */
			info[id].owner = server_asid;
		}

		if (id >= NPORTALS)
			error(INVALID_PORTAL_NUMBER);

		if (info[id].owner != 0 && info[id].owner != server_asid)
			error(NOT_OWNER);

		/* an ugly patch to allow the serial driver to redefine */
		/* handlers */
		if (portal_table[id] != bad_portal &&
		    (id < PORTAL_FD_START && id != SYS_SERIAL_FLUSH_QUEUE))
			error(PORTAL_DEFINED);
		break;

	default:
		error(INVALID_PORTAL_TEMPLATE);
	}

	switch(tolower(template[1])) {
	case 'f':
		stack_save = SAVE_FULL;
		break;
	case 'p':
		stack_save = SAVE_PARTIAL;
		break;
	case 'm':
		stack_save = SAVE_MINIMAL;
		break;
	default:
		error(INVALID_PORTAL_TEMPLATE);
	}

	if (stack_type == STACK_EXCEPTION && stack_save != SAVE_FULL)
		error(INVALID_PORTAL_COMBINATION);

	s = &template[2];
	if (strlen(s) < 1)
		error(INVALID_PORTAL_TEMPLATE);
	if (strlen(s) > MAX_PORTAL_ARGS)
		error(TOO_MANY_PARAMETERS);
	if (stack_type == STACK_QUEUE && strlen(s) > NREG_ARGS)
		error(TOO_MANY_PARAMETERS);

	asid_reg = const_reg = thread_reg = window_reg = bad_vaddr_reg = 0;

	for (i = 0; s[i] != '\0'; i++) {
		switch(tolower(s[i])) {
		case '#':
			/* can deliver the portal # only in first argument */
			/* actually, we leave it there. */
			if (i != 0)
				error(INVALID_PORTAL_TEMPLATE);
			break;

		case 'a':
			if (asid_reg != 0)
				error(INVALID_PORTAL_TEMPLATE);
			if (i >= NREG_ARGS)
				error(INVALID_PORTAL_TEMPLATE);
			asid_reg = A0+i;
			break;

		case 'c':
			if (const_reg != 0)
				error(INVALID_PORTAL_TEMPLATE);
			check_synthetic_arg(id, i, s);
			const_reg = A0+i;
			break;

		case 't':
			if (thread_reg != 0)
				error(INVALID_PORTAL_TEMPLATE);
			check_synthetic_arg(id, i, s);
			thread_reg = A0+i;
			break;

		case 'v':
			if (bad_vaddr_reg != 0)
				error(INVALID_PORTAL_TEMPLATE);
			if (i >= NREG_ARGS)
				error(INVALID_PORTAL_TEMPLATE);
			bad_vaddr_reg = A0+i;
			break;

		case 'w':
		case '>':
		case '=':
			if (window_reg != 0)
				error(INVALID_PORTAL_TEMPLATE);
			if (i >= NREG_ARGS)
				error(INVALID_PORTAL_TEMPLATE);
			window_reg = A0+i;
			window_type = s[i];
			break;

		case 'i':
			/* first parameter must be synthesized by portal code */
			/* first user parameter is clubbered in any case! */
			if (i == 0)
				error(INVALID_PORTAL_TEMPLATE);
			break;

		default:
			error(INVALID_PORTAL_TEMPLATE);
		}
	}

	if (stack_type == STACK_QUEUE && stack_queue[server_asid] == NULL) {
		stack_queue[server_asid] = domain_q_init(server_asid);
		if (stack_queue[server_asid] == NULL ||
		    (int)stack_queue[server_asid] == -1)
			error(MEMORY_ALLOCATION);
	}

	/*
	 * must flush the portal table entry to avoid overwriting the local copy
	 * in virtual memory.
	 */
        clean_cache(portals[install_asid].phys + id, sizeof(Portal));

	/* note: return address is two instructions after entry point */
	info[id].mem = gen_portal(save, entry,
		(int *)((char *)get_domain_entry(server_asid) + 2*sizeof(int)),
		stack_type, stack_save, stack_queue[server_asid],
		thread_reg, const_reg, c, asid_reg, window_reg, window_type,
		bad_vaddr_reg, &portal_len, &const_offset, &c_reg);
	info[id].code = info[id].mem;
	portal_table[id] = v2p(info[id].code);
	info[id].template = strdup(template);
	info[id].constant = c;
	info[id].len = portal_len;
	info[id].const_offset = const_offset;
	info[id].c_reg = c_reg;

	DIAG(PORTAL_DIAG, ("portal_table[%d]=%p\n", id, portal_table[id]));

	/*
	 * must flush the cache for the portal table, since we access it through
	 * cached physical memory.
	 */
        clean_cache(portals[install_asid].virt + id, sizeof(Portal));
	/* must flush again, since calling clean_cache caused caching of */
	/* a portion of the portal table! */
        clean_cache(portals[install_asid].phys + id, sizeof(Portal));

	if (id < NPORTALS)
		info[id].owner = server_asid;

	if (portals[install_asid].notify_id > 0)
		call_portal(portals[install_asid].notify_id, id, template);

	DIAG(PORTAL_DIAG, ("new_portal generated portal %d in asid %d\n",
		id, install_asid));

	return id;
}


/*
 * Create a new portal into the caller's domain using a parameters template
 */
int
sys_portal_create(int caller_asid, int id, char *template, uint c, int (*entry)(), uint install_2up)
{
	int install_asid;
	vlong save[S_REGS];

	DIAG(PORTAL_DIAG,
("sys_portal_create: asid=%d id=%d template=%s c=%08x entry=%p install_2up=%d\n",
		caller_asid, id, template, c, entry, install_2up));

	if (install_2up) {
		install_asid = get_caller_asid(2);
		if (install_asid < 0)
			error(GET_CALLER);
	} else
		install_asid = caller_asid;

	if (get_caller(1, save) < 0)
		error(GET_CALLER);

	id = new_portal(install_asid, id, caller_asid, save, template, c, entry);
	DIAG(PORTAL_DIAG,
		("sys_portal_create generated portal %d in asid %d\n",
		id, install_asid));

	return id;
}


/*
 * Create a new portal into the caller's child using a parameters template
 */
int
sys_portal_create_child(int parent_asid, int child_asid, int id,
			char *template, uint c, int (*entry)())
{
	vlong save[S_REGS];

	DIAG(PORTAL_DIAG,
("sys_portal_create_child: parent_asid=%d child_asid=%d id=%d template=%s c=%d entry=%p\n",
		parent_asid, child_asid, id, template, c, entry));

	if (child_asid <= 0 || child_asid >= NASID)
		error(INVALID_ASID);

	if (portals[child_asid].parent_asid != parent_asid)
		error(NOT_PARENT);

	if (get_caller(1, save) < 0)
		error(GET_CALLER);

	id = new_portal(child_asid, id, parent_asid, save, template, c, entry);
	DIAG(PORTAL_DIAG,
		("sys_portal_create_child generated portal %d in asid %d\n",
		id, child_asid));

	return id;
}


/*
 * Create a new portal into the caller's domain return the entry to the 
 * system calls table.
 * This is a special portal, which DOES NOT add push its state on the
 * activation stack.
 * The first three parameters of the called routine are taken
 * from parameters 2-4 of the portal.
 * Note: there is NO specification string for this kind of portal!
 * No parameter manipulations are performed!
 */
int
sys_portal_create0(int caller_asid, int id, int (*entry)())
{
	vlong save[S_REGS];
	Portal *portal_table;
	Port_Info *info;
	int portal_len;
	char template[NAMELEN];

	DIAG(PORTAL_DIAG,
		("sys_portal_create0: caller_asid=%d id=%d entry=%p\n",
		caller_asid, id, entry));

	if (id <= 0 || id >= NPORTALS)
		error(INVALID_PORTAL_NUMBER);

	if (entry == NULL)
		error(INVALID_ENTRY);

	portal_table = portals[caller_asid].virt;
	info = portals[caller_asid].info;

	if (portal_table == NULL || info == NULL)
		error(INTERNAL_ERROR_PORTALS);

	if (info[id].owner != 0 && info[id].owner != caller_asid)
		error(NOT_OWNER);

	/* an ugly patch to allow the serial driver to redefine the handler */
	if (portal_table[id] != bad_portal && id < PORTAL_FD_START)
		error(PORTAL_DEFINED);

	if (get_caller(1, save) < 0)
		error(GET_CALLER);

	/*
	 * must flush the portal table entry to avoid overwriting the local copy
	 * in virtual memory.
	 */
        clean_cache(portals[caller_asid].phys + id, sizeof(Portal));

	/* note: return address is two instructions after entry point */
	info[id].mem = gen_null_portal(save, entry, &portal_len);
	info[id].code = info[id].mem;
	portal_table[id] = v2p(info[id].code);
	info[id].owner = caller_asid;
	info[id].template = strdup("");
	info[id].len = portal_len;
	info[id].constant = 0;
	info[id].const_offset = 0;
	info[id].c_reg = ZERO;

	/*
	 * must flush the cache for the portal table, since we access it through
	 * cached physical memory.
	 */
        clean_cache(portals[caller_asid].virt + id, sizeof(Portal));
	/* must flush again, since calling clean_cache caused caching of */
	/* a portion of the portal table! */
        clean_cache(portals[caller_asid].phys + id, sizeof(Portal));

	if (portals[caller_asid].notify_id > 0) {
		strlcpy(template, "", NAMELEN);
		call_portal(portals[caller_asid].notify_id, id, template);
	}

	DIAG(PORTAL_DIAG,
		("sys_portal_create0 generated portal %d in asid %d\n",
		id, caller_asid));

	return id;
}


int
sys_portal_delete(int caller_asid, const int id, const int n,
		const uint install_2up)
{
	int asid, i;
	Portal *portal_table;
	Port_Info *info;

	DIAG(PORTAL_DIAG,
	("sys_portal_delete: caller_asid=%d id=%d n=%d install_2up=%d\n",
		caller_asid, id, n, install_2up));

	if (id < 0 || id >= NPORTALS || n < 1 || (id + n) > NPORTALS)
	      error(INVALID_PORTAL_NUMBER);

	if (install_2up) {
		asid = get_caller_asid(2);
		if (asid < 0)
			error(GET_CALLER);
	} else
		asid = caller_asid;

	portal_table = portals[asid].virt;
	info = portals[asid].info;

	if (portal_table == NULL || info == NULL)
		error(INTERNAL_ERROR_PORTALS);

	for (i = 0; i < n; i++)
		if (info[id+i].owner != 0 &&
		    info[id+i].owner != caller_asid)
			error(NOT_OWNER);

	/*
	 * must flush the portal table entry to avoid overwriting the local copy
	 * in virtual memory.
	 */
        clean_cache(portals[asid].phys + id, n*sizeof(Portal));

	for (i = 0; i < n; i++) {
		if (info[id+i].template != NULL)
			free(info[id+i].template);
		if (info[id+i].mem != NULL)
			aligned_decref(info[id+i].mem);
		portal_table[id+i] = bad_portal;
		memset(&info[id+i], 0, sizeof(Port_Info));
	}
	/*
	 * must flush the cache for the portal table, since we access it through
	 * cached physical memory.
	 */
        clean_cache(portals[asid].virt + id, n*sizeof(Portal));
	/* must flush again, since calling clean_cache caused caching of */
	/* a portion of the portal table! */
        clean_cache(portals[asid].phys + id, n*sizeof(Portal));

	return 0;
}


/*
 * Find an existing portal group with the given name and replicate its
 * portals. Return the first portal number of the newly replicated portals.
 *
 * Note: "name" may be not NUL terminated.
 */
int
sys_portal_open(int asid, const char *name, int n)
{
	Elem *e;
	int i, id;
	Portal *portal_table;
	Port_Info *info;
	char template[NAMELEN];

	DIAG(PORTAL_DIAG, ("sys_portal_open for asid=%d name=%s\n",
		asid, name));

        if (name == NULL || param_check(name, NAMELEN, 1) < 0 ||
	    name[0] == '\0')
		error(INVALID_PORTAL_NAME);

	if ((e = portal_lookup(name)) == NULL)
		error(INVALID_PORTAL_NAME);

	if (n != e->n)
		error(INVALID_PORTAL_SET_SIZE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -