Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa18c55b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: hab: add some more logs"

parents 55cc722e dec36d01
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ msm_hab-objs = \
	hab_mem_linux.o \
	hab_pipe.o \
	qvm_comm.o \
	hab_qvm.o
	hab_qvm.o \
	hab_parser.o

obj-$(CONFIG_MSM_HAB) += msm_hab.o
+308 −44
Original line number Diff line number Diff line
@@ -21,25 +21,32 @@
	.openlock = __SPIN_LOCK_UNLOCKED(&hab_devices[__num__].openlock)\
	}

/* the following has to match habmm definitions, order does not matter */
/*
 * The following has to match habmm definitions, order does not matter if
 * hab config does not care either. When hab config is not present, the default
 * is as guest VM all pchans are pchan opener (FE)
 */
static struct hab_device hab_devices[] = {
	HAB_DEVICE_CNSTR(DEVICE_AUD1_NAME, MM_AUD_1, 0),
	HAB_DEVICE_CNSTR(DEVICE_AUD2_NAME, MM_AUD_2, 1),
	HAB_DEVICE_CNSTR(DEVICE_AUD3_NAME, MM_AUD_3, 2),
	HAB_DEVICE_CNSTR(DEVICE_AUD4_NAME, MM_AUD_4, 3),
	HAB_DEVICE_CNSTR(DEVICE_CAM_NAME, MM_CAM, 4),
	HAB_DEVICE_CNSTR(DEVICE_DISP1_NAME, MM_DISP_1, 5),
	HAB_DEVICE_CNSTR(DEVICE_DISP2_NAME, MM_DISP_2, 6),
	HAB_DEVICE_CNSTR(DEVICE_DISP3_NAME, MM_DISP_3, 7),
	HAB_DEVICE_CNSTR(DEVICE_DISP4_NAME, MM_DISP_4, 8),
	HAB_DEVICE_CNSTR(DEVICE_DISP5_NAME, MM_DISP_5, 9),
	HAB_DEVICE_CNSTR(DEVICE_GFX_NAME, MM_GFX, 10),
	HAB_DEVICE_CNSTR(DEVICE_VID_NAME, MM_VID, 11),
	HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 12),
	HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 13),
	HAB_DEVICE_CNSTR(DEVICE_QCPE2_NAME, MM_QCPE_VM2, 14),
	HAB_DEVICE_CNSTR(DEVICE_QCPE3_NAME, MM_QCPE_VM3, 15),
	HAB_DEVICE_CNSTR(DEVICE_QCPE4_NAME, MM_QCPE_VM4, 16)
	HAB_DEVICE_CNSTR(DEVICE_CAM1_NAME, MM_CAM_1, 4),
	HAB_DEVICE_CNSTR(DEVICE_CAM2_NAME, MM_CAM_2, 5),
	HAB_DEVICE_CNSTR(DEVICE_DISP1_NAME, MM_DISP_1, 6),
	HAB_DEVICE_CNSTR(DEVICE_DISP2_NAME, MM_DISP_2, 7),
	HAB_DEVICE_CNSTR(DEVICE_DISP3_NAME, MM_DISP_3, 8),
	HAB_DEVICE_CNSTR(DEVICE_DISP4_NAME, MM_DISP_4, 9),
	HAB_DEVICE_CNSTR(DEVICE_DISP5_NAME, MM_DISP_5, 10),
	HAB_DEVICE_CNSTR(DEVICE_GFX_NAME, MM_GFX, 11),
	HAB_DEVICE_CNSTR(DEVICE_VID_NAME, MM_VID, 12),
	HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 13),
	HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 14),
	HAB_DEVICE_CNSTR(DEVICE_QCPE2_NAME, MM_QCPE_VM2, 15),
	HAB_DEVICE_CNSTR(DEVICE_QCPE3_NAME, MM_QCPE_VM3, 16),
	HAB_DEVICE_CNSTR(DEVICE_QCPE4_NAME, MM_QCPE_VM4, 17),
	HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 18),
	HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 19),
};

struct hab_driver hab_driver = {
@@ -71,6 +78,7 @@ struct uhab_context *hab_ctx_alloc(int kernel)
	kref_init(&ctx->refcount);
	ctx->import_ctx = habmem_imp_hyp_open();
	if (!ctx->import_ctx) {
		pr_err("habmem_imp_hyp_open failed\n");
		kfree(ctx);
		return NULL;
	}
@@ -148,6 +156,7 @@ struct virtual_channel *frontend_open(struct uhab_context *ctx,

	dev = find_hab_device(mm_id);
	if (dev == NULL) {
		pr_err("HAB device %d is not initialized\n", mm_id);
		ret = -EINVAL;
		goto err;
	}
@@ -161,6 +170,7 @@ struct virtual_channel *frontend_open(struct uhab_context *ctx,

	vchan = hab_vchan_alloc(ctx, pchan);
	if (!vchan) {
		pr_err("vchan alloc failed\n");
		ret = -ENOMEM;
		goto err;
	}
@@ -187,6 +197,9 @@ struct virtual_channel *frontend_open(struct uhab_context *ctx,
	vchan->otherend_id = recv_request->vchan_id;
	hab_open_request_free(recv_request);

	vchan->session_id = open_id;
	pr_debug("vchan->session_id:%d\n", vchan->session_id);

	/* Send Ack sequence */
	hab_open_request_init(&request, HAB_PAYLOAD_TYPE_ACK, pchan,
		0, sub_id, open_id);
@@ -221,6 +234,7 @@ struct virtual_channel *backend_listen(struct uhab_context *ctx,

	dev = find_hab_device(mm_id);
	if (dev == NULL) {
		pr_err("failed to find dev based on id %d\n", mm_id);
		ret = -EINVAL;
		goto err;
	}
@@ -249,6 +263,9 @@ struct virtual_channel *backend_listen(struct uhab_context *ctx,

		vchan->otherend_id = otherend_vchan_id;

		vchan->session_id = open_id;
		pr_debug("vchan->session_id:%d\n", vchan->session_id);

		/* Send Init-Ack sequence */
		hab_open_request_init(&request, HAB_PAYLOAD_TYPE_INIT_ACK,
				pchan, vchan->id, sub_id, open_id);
@@ -259,7 +276,7 @@ struct virtual_channel *backend_listen(struct uhab_context *ctx,
		/* Wait for Ack sequence */
		hab_open_request_init(&request, HAB_PAYLOAD_TYPE_ACK,
				pchan, 0, sub_id, open_id);
		ret = hab_open_listen(ctx, dev, &request, &recv_request, HZ);
		ret = hab_open_listen(ctx, dev, &request, &recv_request, 0);

		if (ret != -EAGAIN)
			break;
@@ -280,6 +297,7 @@ struct virtual_channel *backend_listen(struct uhab_context *ctx,
	hab_pchan_put(pchan);
	return vchan;
err:
	pr_err("listen on mmid %d failed\n", mm_id);
	if (vchan)
		hab_vchan_put(vchan);
	if (pchan)
@@ -304,12 +322,19 @@ long hab_vchan_send(struct uhab_context *ctx,
	}

	vchan = hab_get_vchan_fromvcid(vcid, ctx);
	if (!vchan || vchan->otherend_closed)
		return -ENODEV;
	if (!vchan || vchan->otherend_closed) {
		ret = -ENODEV;
		goto err;
	}

	HAB_HEADER_SET_SIZE(header, sizebytes);
	if (flags & HABMM_SOCKET_SEND_FLAGS_XING_VM_STAT)
		HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_PROFILE);
	else
		HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_MSG);

	HAB_HEADER_SET_ID(header, vchan->otherend_id);
	HAB_HEADER_SET_SESSION_ID(header, vchan->session_id);

	while (1) {
		ret = physical_channel_send(vchan->pchan, &header, data);
@@ -321,7 +346,11 @@ long hab_vchan_send(struct uhab_context *ctx,
		schedule();
	}


err:
	if (vchan)
		hab_vchan_put(vchan);

	return ret;
}

@@ -335,7 +364,7 @@ struct hab_message *hab_vchan_recv(struct uhab_context *ctx,
	int nonblocking_flag = flags & HABMM_SOCKET_RECV_FLAGS_NON_BLOCKING;

	vchan = hab_get_vchan_fromvcid(vcid, ctx);
	if (!vchan || vchan->otherend_closed)
	if (!vchan)
		return ERR_PTR(-ENODEV);

	if (nonblocking_flag) {
@@ -351,6 +380,8 @@ struct hab_message *hab_vchan_recv(struct uhab_context *ctx,
	if (!message) {
		if (nonblocking_flag)
			ret = -EAGAIN;
		else if (vchan->otherend_closed)
			ret = -ENODEV;
		else
			ret = -EPIPE;
	}
@@ -369,7 +400,11 @@ int hab_vchan_open(struct uhab_context *ctx,
		int32_t *vcid,
		uint32_t flags)
{
	struct virtual_channel *vchan;
	struct virtual_channel *vchan = NULL;
	struct hab_device *dev;

	pr_debug("Open mmid=%d, loopback mode=%d, loopback num=%d\n",
		mmid, hab_driver.b_loopback, hab_driver.loopback_num);

	if (!vcid)
		return -EINVAL;
@@ -383,14 +418,29 @@ int hab_vchan_open(struct uhab_context *ctx,
			vchan = frontend_open(ctx, mmid, LOOPBACK_DOM);
		}
	} else {
		if (hab_driver.b_server_dom)
		dev = find_hab_device(mmid);

		if (dev) {
			struct physical_channel *pchan =
			hab_pchan_find_domid(dev, HABCFG_VMID_DONT_CARE);

			if (pchan->is_be)
				vchan = backend_listen(ctx, mmid);
			else
			vchan = frontend_open(ctx, mmid, 0);
				vchan = frontend_open(ctx, mmid,
						HABCFG_VMID_DONT_CARE);
		} else {
			pr_err("failed to find device, mmid %d\n", mmid);
		}
	}

	if (IS_ERR(vchan))
	if (IS_ERR(vchan)) {
		pr_err("vchan open failed over mmid=%d\n", mmid);
		return PTR_ERR(vchan);
	}

	pr_debug("vchan id %x, remote id %x\n",
		vchan->id, vchan->otherend_id);

	write_lock(&ctx->ctx_lock);
	list_add_tail(&vchan->node, &ctx->vchannels);
@@ -403,12 +453,13 @@ int hab_vchan_open(struct uhab_context *ctx,

void hab_send_close_msg(struct virtual_channel *vchan)
{
	struct hab_header header;
	struct hab_header header = {0};

	if (vchan && !vchan->otherend_closed) {
		HAB_HEADER_SET_SIZE(header, 0);
		HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_CLOSE);
		HAB_HEADER_SET_ID(header, vchan->otherend_id);
		HAB_HEADER_SET_SESSION_ID(header, vchan->session_id);
		physical_channel_send(vchan->pchan, &header, NULL);
	}
}
@@ -442,6 +493,220 @@ void hab_vchan_close(struct uhab_context *ctx, int32_t vcid)
	write_unlock(&ctx->ctx_lock);
}

/*
 * To name the pchan - the pchan has two ends, either FE or BE locally.
 * if is_be is true, then this is listener for BE. pchane name use remote
 * FF's vmid from the table.
 * if is_be is false, then local is FE as opener. pchan name use local FE's
 * vmid (self)
 */
static int hab_initialize_pchan_entry(struct hab_device *mmid_device,
				int vmid_local, int vmid_remote, int is_be)
{
	char pchan_name[MAX_VMID_NAME_SIZE];
	struct physical_channel *pchan = NULL;
	int ret;
	int vmid = is_be ? vmid_remote : vmid_local;

	if (!mmid_device) {
		pr_err("habdev %pK, vmid local %d, remote %d, is be %d\n",
				mmid_device, vmid_local, vmid_remote, is_be);
		return -EINVAL;
	}

	snprintf(pchan_name, MAX_VMID_NAME_SIZE, "vm%d-", vmid);
	strlcat(pchan_name, mmid_device->name, MAX_VMID_NAME_SIZE);

	ret = habhyp_commdev_alloc((void **)&pchan, is_be, pchan_name,
					vmid_remote, mmid_device);
	if (ret == 0) {
		pr_debug("pchan %s added, vmid local %d, remote %d, is_be %d, total %d\n",
				pchan_name, vmid_local, vmid_remote, is_be,
				mmid_device->pchan_cnt);
	} else {
		pr_err("failed %d to allocate pchan %s, vmid local %d, remote %d, is_be %d, total %d\n",
				ret, pchan_name, vmid_local, vmid_remote,
				is_be, mmid_device->pchan_cnt);
	}

	return ret;
}

static void hab_generate_pchan(struct local_vmid *settings, int i, int j)
{
	int k, ret = 0;

	pr_debug("%d as mmid %d in vmid %d\n",
			HABCFG_GET_MMID(settings, i, j), j, i);

	switch (HABCFG_GET_MMID(settings, i, j)) {
	case MM_AUD_START/100:
		for (k = MM_AUD_START + 1; k < MM_AUD_END; k++) {
			/*
			 * if this local pchan end is BE, then use
			 * remote FE's vmid. If local end is FE, then
			 * use self vmid
			 */
			ret += hab_initialize_pchan_entry(
					find_hab_device(k),
					settings->self,
					HABCFG_GET_VMID(settings, i),
					HABCFG_GET_BE(settings, i, j));
		}
		break;

	case MM_CAM_START/100:
		for (k = MM_CAM_START + 1; k < MM_CAM_END; k++) {
			ret += hab_initialize_pchan_entry(
					find_hab_device(k),
					settings->self,
					HABCFG_GET_VMID(settings, i),
					HABCFG_GET_BE(settings, i, j));
		}
		break;

	case MM_DISP_START/100:
		for (k = MM_DISP_START + 1; k < MM_DISP_END; k++) {
			ret += hab_initialize_pchan_entry(
					find_hab_device(k),
					settings->self,
					HABCFG_GET_VMID(settings, i),
					HABCFG_GET_BE(settings, i, j));
		}
		break;

	case MM_GFX_START/100:
		for (k = MM_GFX_START + 1; k < MM_GFX_END; k++) {
			ret += hab_initialize_pchan_entry(
					find_hab_device(k),
					settings->self,
					HABCFG_GET_VMID(settings, i),
					HABCFG_GET_BE(settings, i, j));
		}
		break;

	case MM_VID_START/100:
		for (k = MM_VID_START + 1; k < MM_VID_END; k++) {
			ret += hab_initialize_pchan_entry(
					find_hab_device(k),
					settings->self,
					HABCFG_GET_VMID(settings, i),
					HABCFG_GET_BE(settings, i, j));
		}
		break;

	case MM_MISC_START/100:
		for (k = MM_MISC_START + 1; k < MM_MISC_END; k++) {
			ret += hab_initialize_pchan_entry(
					find_hab_device(k),
					settings->self,
					HABCFG_GET_VMID(settings, i),
					HABCFG_GET_BE(settings, i, j));
		}
		break;

	case MM_QCPE_START/100:
		for (k = MM_QCPE_START + 1; k < MM_QCPE_END; k++) {
			ret += hab_initialize_pchan_entry(
					find_hab_device(k),
					settings->self,
					HABCFG_GET_VMID(settings, i),
					HABCFG_GET_BE(settings, i, j));
		}
		break;

	case MM_CLK_START/100:
		for (k = MM_CLK_START + 1; k < MM_CLK_END; k++) {
			ret += hab_initialize_pchan_entry(
					find_hab_device(k),
					settings->self,
					HABCFG_GET_VMID(settings, i),
					HABCFG_GET_BE(settings, i, j));
		}
		break;

	default:
		pr_err("failed to find mmid %d, i %d, j %d\n",
			HABCFG_GET_MMID(settings, i, j), i, j);

		break;
	}
}

/*
 * generate pchan list based on hab settings table.
 * return status 0: success, otherwise failure
 */
static int hab_generate_pchan_list(struct local_vmid *settings)
{
	int i, j;

	/* scan by valid VMs, then mmid */
	pr_debug("self vmid is %d\n", settings->self);
	for (i = 0; i < HABCFG_VMID_MAX; i++) {
		if (HABCFG_GET_VMID(settings, i) != HABCFG_VMID_INVALID &&
			HABCFG_GET_VMID(settings, i) != settings->self) {
			pr_debug("create pchans for vm %d\n", i);

			for (j = 1; j <= HABCFG_MMID_AREA_MAX; j++) {
				if (HABCFG_GET_MMID(settings, i, j)
						!= HABCFG_VMID_INVALID)
					hab_generate_pchan(settings, i, j);
			}
		}
	}

	return 0;
}

/*
 * This function checks hypervisor plug-in readiness, read in hab configs,
 * and configure pchans
 */
int do_hab_parse(void)
{
	int result;
	int i;
	struct hab_device *device;
	int pchan_total = 0;

	/* first check if hypervisor plug-in is ready */
	result = hab_hypervisor_register();
	if (result) {
		pr_err("register HYP plug-in failed, ret %d\n", result);
		return result;
	}

	/* Initialize open Q before first pchan starts */
	for (i = 0; i < hab_driver.ndevices; i++) {
		device = &hab_driver.devp[i];
		init_waitqueue_head(&device->openq);
	}

	/* read in hab config and create pchans*/
	memset(&hab_driver.settings, HABCFG_VMID_INVALID,
				sizeof(hab_driver.settings));

	pr_debug("prepare default gvm 2 settings...\n");
	fill_default_gvm_settings(&hab_driver.settings, 2,
					MM_AUD_START, MM_ID_MAX);

	/* now generate hab pchan list */
	result  = hab_generate_pchan_list(&hab_driver.settings);
	if (result) {
		pr_err("generate pchan list failed, ret %d\n", result);
	} else {
		for (i = 0; i < hab_driver.ndevices; i++) {
			device = &hab_driver.devp[i];
			pchan_total += device->pchan_cnt;
		}
		pr_debug("ret %d, total %d pchans added, ndevices %d\n",
				 result, pchan_total, hab_driver.ndevices);
	}

	return result;
}

static int hab_open(struct inode *inodep, struct file *filep)
{
	int result = 0;
@@ -468,6 +733,8 @@ static int hab_release(struct inode *inodep, struct file *filep)
	if (!ctx)
		return 0;

	pr_debug("inode %pK, filep %pK\n", inodep, filep);

	write_lock(&ctx->ctx_lock);

	list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
@@ -635,9 +902,7 @@ static const struct dma_map_ops hab_dma_ops = {
static int __init hab_init(void)
{
	int result;
	int i;
	dev_t dev;
	struct hab_device *device;

	result = alloc_chrdev_region(&hab_driver.major, 0, 1, "hab");

@@ -676,13 +941,10 @@ static int __init hab_init(void)
		goto err;
	}

	for (i = 0; i < hab_driver.ndevices; i++) {
		device = &hab_driver.devp[i];
		init_waitqueue_head(&device->openq);
	}

	hab_hypervisor_register();
	/* read in hab config, then configure pchans */
	result = do_hab_parse();

	if (!result) {
		hab_driver.kctx = hab_ctx_alloc(1);
		if (!hab_driver.kctx) {
			pr_err("hab_ctx_alloc failed");
@@ -694,6 +956,7 @@ static int __init hab_init(void)
		set_dma_ops(hab_driver.dev, &hab_dma_ops);

		return result;
	}

err:
	if (!IS_ERR_OR_NULL(hab_driver.dev))
@@ -703,6 +966,7 @@ err:
	cdev_del(&hab_driver.cdev);
	unregister_chrdev_region(dev, 1);

	pr_err("Error in hab init, result %d\n", result);
	return result;
}

+111 −21
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@
#ifndef __HAB_H
#define __HAB_H

#define pr_fmt(fmt) "hab: " fmt
#define pr_fmt(fmt) "|hab:%s:%d|" fmt, __func__, __LINE__

#include <linux/types.h>

@@ -47,6 +47,7 @@ enum hab_payload_type {
	HAB_PAYLOAD_TYPE_EXPORT_ACK,
	HAB_PAYLOAD_TYPE_PROFILE,
	HAB_PAYLOAD_TYPE_CLOSE,
	HAB_PAYLOAD_TYPE_MAX,
};
#define LOOPBACK_DOM 0xFF

@@ -61,7 +62,8 @@ enum hab_payload_type {
#define DEVICE_AUD2_NAME "hab_aud2"
#define DEVICE_AUD3_NAME "hab_aud3"
#define DEVICE_AUD4_NAME "hab_aud4"
#define DEVICE_CAM_NAME "hab_cam"
#define DEVICE_CAM1_NAME "hab_cam1"
#define DEVICE_CAM2_NAME "hab_cam2"
#define DEVICE_DISP1_NAME "hab_disp1"
#define DEVICE_DISP2_NAME "hab_disp2"
#define DEVICE_DISP3_NAME "hab_disp3"
@@ -74,6 +76,48 @@ enum hab_payload_type {
#define DEVICE_QCPE2_NAME "hab_qcpe_vm2"
#define DEVICE_QCPE3_NAME "hab_qcpe_vm3"
#define DEVICE_QCPE4_NAME "hab_qcpe_vm4"
#define DEVICE_CLK1_NAME "hab_clock_vm1"
#define DEVICE_CLK2_NAME "hab_clock_vm2"

/* make sure concascaded name is less than this value */
#define MAX_VMID_NAME_SIZE 30

#define HABCFG_FILE_SIZE_MAX   256
#define HABCFG_MMID_AREA_MAX   (MM_ID_MAX/100)

#define HABCFG_VMID_MAX        16
#define HABCFG_VMID_INVALID    (-1)
#define HABCFG_VMID_DONT_CARE  (-2)

#define HABCFG_ID_LINE_LIMIT   ","
#define HABCFG_ID_VMID         "VMID="
#define HABCFG_ID_BE           "BE="
#define HABCFG_ID_FE           "FE="
#define HABCFG_ID_MMID         "MMID="
#define HABCFG_ID_RANGE        "-"
#define HABCFG_ID_DONTCARE     "X"

#define HABCFG_FOUND_VMID      1
#define HABCFG_FOUND_FE_MMIDS  2
#define HABCFG_FOUND_BE_MMIDS  3
#define HABCFG_FOUND_NOTHING   (-1)

#define HABCFG_BE_FALSE        0
#define HABCFG_BE_TRUE         1

#define HABCFG_GET_VMID(_local_cfg_, _vmid_) \
	((settings)->vmid_mmid_list[_vmid_].vmid)
#define HABCFG_GET_MMID(_local_cfg_, _vmid_, _mmid_) \
	((settings)->vmid_mmid_list[_vmid_].mmid[_mmid_])
#define HABCFG_GET_BE(_local_cfg_, _vmid_, _mmid_) \
	((settings)->vmid_mmid_list[_vmid_].is_listener[_mmid_])

struct hab_header {
	uint32_t id_type_size;
	uint32_t session_id;
	uint32_t signature;
	uint32_t sequence;
} __packed;

/* "Size" of the HAB_HEADER_ID and HAB_VCID_ID must match */
#define HAB_HEADER_SIZE_SHIFT 0
@@ -96,34 +140,44 @@ enum hab_payload_type {
#define HAB_VCID_GET_ID(vcid) \
	(((vcid) & HAB_VCID_ID_MASK) >> HAB_VCID_ID_SHIFT)


#define HAB_HEADER_SET_SESSION_ID(header, sid) ((header).session_id = (sid))

#define HAB_HEADER_SET_SIZE(header, size) \
	((header).info = (((header).info) & (~HAB_HEADER_SIZE_MASK)) | \
		(((size) << HAB_HEADER_SIZE_SHIFT) & HAB_HEADER_SIZE_MASK))
	((header).id_type_size = ((header).id_type_size & \
			(~HAB_HEADER_SIZE_MASK)) | \
			(((size) << HAB_HEADER_SIZE_SHIFT) & \
			HAB_HEADER_SIZE_MASK))

#define HAB_HEADER_SET_TYPE(header, type) \
	((header).info = (((header).info) & (~HAB_HEADER_TYPE_MASK)) | \
		(((type) << HAB_HEADER_TYPE_SHIFT) & HAB_HEADER_TYPE_MASK))
	((header).id_type_size = ((header).id_type_size & \
			(~HAB_HEADER_TYPE_MASK)) | \
			(((type) << HAB_HEADER_TYPE_SHIFT) & \
			HAB_HEADER_TYPE_MASK))

#define HAB_HEADER_SET_ID(header, id) \
	((header).info = (((header).info) & (~HAB_HEADER_ID_MASK)) | \
		((HAB_VCID_GET_ID(id) << HAB_HEADER_ID_SHIFT) \
		& HAB_HEADER_ID_MASK))
	((header).id_type_size = ((header).id_type_size & \
			(~HAB_HEADER_ID_MASK)) | \
			((HAB_VCID_GET_ID(id) << HAB_HEADER_ID_SHIFT) & \
			HAB_HEADER_ID_MASK))

#define HAB_HEADER_GET_SIZE(header) \
	((((header).info) & HAB_HEADER_SIZE_MASK) >> HAB_HEADER_SIZE_SHIFT)
	(((header).id_type_size & \
		HAB_HEADER_SIZE_MASK) >> HAB_HEADER_SIZE_SHIFT)

#define HAB_HEADER_GET_TYPE(header) \
	((((header).info) & HAB_HEADER_TYPE_MASK) >> HAB_HEADER_TYPE_SHIFT)
	(((header).id_type_size & \
		HAB_HEADER_TYPE_MASK) >> HAB_HEADER_TYPE_SHIFT)

#define HAB_HEADER_GET_ID(header) \
	(((((header).info) & HAB_HEADER_ID_MASK) >> \
	((((header).id_type_size & HAB_HEADER_ID_MASK) >> \
	(HAB_HEADER_ID_SHIFT - HAB_VCID_ID_SHIFT)) & HAB_VCID_ID_MASK)

struct hab_header {
	uint32_t info;
};
#define HAB_HEADER_GET_SESSION_ID(header) ((header).session_id)

struct physical_channel {
	char name[MAX_VMID_NAME_SIZE];
	int is_be;
	struct kref refcount;
	struct hab_device *habdev;
	struct list_head node;
@@ -138,6 +192,10 @@ struct physical_channel {
	int closed;

	spinlock_t rxbuf_lock;

	/* vchans over this pchan */
	struct list_head vchannels;
	rwlock_t vchans_lock;
};

struct hab_open_send_data {
@@ -179,9 +237,10 @@ struct hab_message {
};

struct hab_device {
	const char *name;
	char name[MAX_VMID_NAME_SIZE];
	unsigned int id;
	struct list_head pchannels;
	int pchan_cnt;
	struct mutex pchan_lock;
	struct list_head openq_list;
	spinlock_t openlock;
@@ -211,19 +270,37 @@ struct uhab_context {
	int kernel;
};

/*
 * array to describe the VM and its MMID configuration as what is connected to
 * so this is describing a pchan's remote side
 */
struct vmid_mmid_desc {
	int vmid; /* remote vmid  */
	int mmid[HABCFG_MMID_AREA_MAX+1]; /* selected or not */
	int is_listener[HABCFG_MMID_AREA_MAX+1]; /* yes or no */
};

struct local_vmid {
	int32_t self; /* only this field is for local */
	struct vmid_mmid_desc vmid_mmid_list[HABCFG_VMID_MAX];
};

struct hab_driver {
	struct device *dev;
	struct cdev cdev;
	dev_t major;
	struct class *class;
	int irq;

	int ndevices;
	struct hab_device *devp;
	struct uhab_context *kctx;

	struct local_vmid settings; /* parser results */

	int b_server_dom;
	int loopback_num;
	int b_loopback;

	void *hyp_priv; /* hypervisor plug-in storage */
};

struct virtual_channel {
@@ -243,12 +320,14 @@ struct virtual_channel {
	struct physical_channel *pchan;
	struct uhab_context *ctx;
	struct list_head node;
	struct list_head pnode;
	struct list_head rx_list;
	wait_queue_head_t rx_queue;
	spinlock_t rx_lock;
	int id;
	int otherend_id;
	int otherend_closed;
	uint32_t session_id;
};

/*
@@ -271,7 +350,7 @@ struct export_desc {
	void *kva;
	int                 payload_count;
	unsigned char       payload[1];
};
} __packed;

int hab_vchan_open(struct uhab_context *ctx,
		unsigned int mmid, int32_t *vcid, uint32_t flags);
@@ -286,6 +365,7 @@ struct hab_message *hab_vchan_recv(struct uhab_context *ctx,
				int vcid,
				unsigned int flags);
void hab_vchan_stop(struct virtual_channel *vchan);
void hab_vchans_stop(struct physical_channel *pchan);
void hab_vchan_stop_notify(struct virtual_channel *vchan);

int hab_mem_export(struct uhab_context *ctx,
@@ -350,7 +430,7 @@ void hab_open_request_init(struct hab_open_request *request,
		int open_id);
int hab_open_request_send(struct hab_open_request *request);
int hab_open_request_add(struct physical_channel *pchan,
		struct hab_header *header);
		size_t sizebytes, int request_type);
void hab_open_request_free(struct hab_open_request *request);
int hab_open_listen(struct uhab_context *ctx,
		struct hab_device *dev,
@@ -361,7 +441,7 @@ int hab_open_listen(struct uhab_context *ctx,
struct virtual_channel *hab_vchan_alloc(struct uhab_context *ctx,
		struct physical_channel *pchan);
struct virtual_channel *hab_vchan_get(struct physical_channel *pchan,
		uint32_t vchan_id);
						  struct hab_header *header);
void hab_vchan_put(struct virtual_channel *vchan);

struct virtual_channel *hab_get_vchan_fromvcid(int32_t vcid,
@@ -394,6 +474,9 @@ static inline void hab_ctx_put(struct uhab_context *ctx)
void hab_send_close_msg(struct virtual_channel *vchan);
int hab_hypervisor_register(void);
void hab_hypervisor_unregister(void);
int habhyp_commdev_alloc(void **commdev, int is_be, char *name,
		int vmid_remote, struct hab_device *mmid_device);
int habhyp_commdev_dealloc(void *commdev);

int physical_channel_read(struct physical_channel *pchan,
		void *payload,
@@ -407,6 +490,13 @@ void physical_channel_rx_dispatch(unsigned long physical_channel);

int loopback_pchan_create(char *dev_name);

int hab_parse(struct local_vmid *settings);

int do_hab_parse(void);

int fill_default_gvm_settings(struct local_vmid *settings,
		int vmid_local, int mmid_start, int mmid_end);

bool hab_is_loopback(void);

/* Global singleton HAB instance */
+39 −5
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ struct importer_context {
	int cnt; /* pages allocated for local file */
	struct list_head imp_list;
	struct file *filp;
	rwlock_t implist_lock;
};

void *habmm_hyp_allocate_grantable(int page_count,
@@ -73,8 +74,12 @@ static int habmem_get_dma_pages(unsigned long address,
	int fd;

	vma = find_vma(current->mm, address);
	if (!vma || !vma->vm_file)
	if (!vma || !vma->vm_file) {
		pr_err("cannot find vma\n");
		goto err;
	}

	pr_debug("vma flags %lx\n", vma->vm_flags);

	/* Look for the fd that matches this the vma file */
	fd = iterate_fd(current->files, 0, match_file, vma->vm_file);
@@ -103,6 +108,7 @@ static int habmem_get_dma_pages(unsigned long address,

	for_each_sg(sg_table->sgl, s, sg_table->nents, i) {
		page = sg_page(s);
		pr_debug("sgl length %d\n", s->length);

		for (j = page_offset; j < (s->length >> PAGE_SHIFT); j++) {
			pages[rc] = nth_page(page, j);
@@ -136,6 +142,12 @@ err:
	return rc;
}

/*
 * exporter - grant & revoke
 * degenerate sharabled page list based on CPU friendly virtual "address".
 * The result as an array is stored in ppdata to return to caller
 * page size 4KB is assumed
 */
int habmem_hyp_grant_user(unsigned long address,
		int page_count,
		int flags,
@@ -220,6 +232,7 @@ void *habmem_imp_hyp_open(void)
	if (!priv)
		return NULL;

	rwlock_init(&priv->implist_lock);
	INIT_LIST_HEAD(&priv->imp_list);

	return priv;
@@ -261,7 +274,7 @@ long habmem_imp_hyp_map(void *imp_ctx,
		uint32_t userflags)
{
	struct page **pages;
	struct compressed_pfns *pfn_table = impdata;
	struct compressed_pfns *pfn_table = (struct compressed_pfns *)impdata;
	struct pages_list *pglist;
	struct importer_context *priv = imp_ctx;
	unsigned long pfn;
@@ -310,6 +323,9 @@ long habmem_imp_hyp_map(void *imp_ctx,
			kfree(pglist);
			pr_err("%ld pages vmap failed\n", pglist->npages);
			return -ENOMEM;
		} else {
			pr_debug("%ld pages vmap pass, return %pK\n",
				pglist->npages, pglist->kva);
		}

		pglist->uva = NULL;
@@ -320,8 +336,11 @@ long habmem_imp_hyp_map(void *imp_ctx,
		pglist->kva = NULL;
	}

	write_lock(&priv->implist_lock);
	list_add_tail(&pglist->list,  &priv->imp_list);
	priv->cnt++;
	write_unlock(&priv->implist_lock);
	pr_debug("index returned %llx\n", *index);

	return 0;
}
@@ -333,11 +352,15 @@ long habmm_imp_hyp_unmap(void *imp_ctx,
		int kernel)
{
	struct importer_context *priv = imp_ctx;
	struct pages_list *pglist;
	struct pages_list *pglist, *tmp;
	int found = 0;
	uint64_t pg_index = index >> PAGE_SHIFT;

	list_for_each_entry(pglist, &priv->imp_list, list) {
	write_lock(&priv->implist_lock);
	list_for_each_entry_safe(pglist, tmp, &priv->imp_list, list) {
		pr_debug("node pglist %pK, kernel %d, pg_index %llx\n",
			pglist, pglist->kernel, pg_index);

		if (kernel) {
			if (pglist->kva == (void *)((uintptr_t)index))
				found  = 1;
@@ -353,11 +376,15 @@ long habmm_imp_hyp_unmap(void *imp_ctx,
		}
	}

	write_unlock(&priv->implist_lock);
	if (!found) {
		pr_err("failed to find export id on index %llx\n", index);
		return -EINVAL;
	}

	pr_debug("detach pglist %pK, index %llx, kernel %d, list cnt %d\n",
		pglist, pglist->index, pglist->kernel, priv->cnt);

	if (kernel)
		if (pglist->kva)
			vunmap(pglist->kva);
@@ -393,6 +420,8 @@ static int hab_map_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
		return VM_FAULT_SIGBUS;
	}

	pr_debug("Fault page index %d\n", page_idx);

	page = pglist->pages[page_idx];
	get_page(page);
	vmf->page = page;
@@ -422,15 +451,20 @@ int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma)
	struct pages_list *pglist;
	int bfound = 0;

	pr_debug("mmap request start %lX, len %ld, index %lX\n",
		vma->vm_start, length, vma->vm_pgoff);

	read_lock(&imp_ctx->implist_lock);
	list_for_each_entry(pglist, &imp_ctx->imp_list, list) {
		if (pglist->index == vma->vm_pgoff) {
			bfound = 1;
			break;
		}
	}
	read_unlock(&imp_ctx->implist_lock);

	if (!bfound) {
		pr_err("Failed to find pglist vm_pgoff: %d\n", vma->vm_pgoff);
		pr_err("Failed to find pglist vm_pgoff: %ld\n", vma->vm_pgoff);
		return -EINVAL;
	}

+22 −4

File changed.

Preview size limit exceeded, changes collapsed.

Loading