summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/soc/qcom/hab/ghs_comm.c33
-rw-r--r--drivers/soc/qcom/hab/hab.c213
-rw-r--r--drivers/soc/qcom/hab/hab.h21
-rw-r--r--drivers/soc/qcom/hab/hab_ghs.c4
-rw-r--r--drivers/soc/qcom/hab/hab_mem_linux.c3
-rw-r--r--drivers/soc/qcom/hab/hab_mimex.c77
-rw-r--r--drivers/soc/qcom/hab/hab_msg.c44
-rw-r--r--drivers/soc/qcom/hab/hab_open.c50
-rw-r--r--drivers/soc/qcom/hab/hab_parser.c7
-rw-r--r--drivers/soc/qcom/hab/hab_pchan.c9
-rw-r--r--drivers/soc/qcom/hab/hab_stat.c57
-rw-r--r--drivers/soc/qcom/hab/hab_vchan.c30
-rw-r--r--drivers/soc/qcom/hab/khab.c4
13 files changed, 356 insertions, 196 deletions
diff --git a/drivers/soc/qcom/hab/ghs_comm.c b/drivers/soc/qcom/hab/ghs_comm.c
index 1fdb1668295c..fbd579793879 100644
--- a/drivers/soc/qcom/hab/ghs_comm.c
+++ b/drivers/soc/qcom/hab/ghs_comm.c
@@ -20,19 +20,28 @@ int physical_channel_read(struct physical_channel *pchan,
{
struct ghs_vdev *dev = (struct ghs_vdev *)pchan->hyp_data;
+ if (!payload || !dev->read_data) {
+ pr_err("invalid parameters %pK %pK offset %d read %zd\n",
+ payload, dev->read_data, dev->read_offset, read_size);
+ return 0;
+ }
+
/* size in header is only for payload excluding the header itself */
- if (dev->read_size < read_size + sizeof(struct hab_header)) {
- pr_warn("read %zd is less than requested %zd plus header %zd\n",
- dev->read_size, read_size, sizeof(struct hab_header));
- read_size = dev->read_size;
+ if (dev->read_size < read_size + sizeof(struct hab_header) +
+ dev->read_offset) {
+ pr_warn("read %zd is less than requested %zd header %zd offset %d\n",
+ dev->read_size, read_size,
+ sizeof(struct hab_header), dev->read_offset);
+ read_size = dev->read_size - dev->read_offset -
+ sizeof(struct hab_header);
}
/* always skip the header */
memcpy(payload, (unsigned char *)dev->read_data +
sizeof(struct hab_header) + dev->read_offset, read_size);
- dev->read_offset += read_size;
+ dev->read_offset += (int)read_size;
- return read_size;
+ return (int)read_size;
}
int physical_channel_send(struct physical_channel *pchan,
@@ -41,8 +50,8 @@ int physical_channel_send(struct physical_channel *pchan,
{
size_t sizebytes = HAB_HEADER_GET_SIZE(*header);
struct ghs_vdev *dev = (struct ghs_vdev *)pchan->hyp_data;
- GIPC_Result result;
- uint8_t *msg;
+ GIPC_Result result = GIPC_Success;
+ uint8_t *msg = NULL;
spin_lock_bh(&dev->io_lock);
@@ -61,7 +70,7 @@ int physical_channel_send(struct physical_channel *pchan,
}
if (HAB_HEADER_GET_TYPE(*header) == HAB_PAYLOAD_TYPE_PROFILE) {
- struct timeval tv;
+ struct timeval tv = {0};
struct habmm_xing_vm_stat *pstat =
(struct habmm_xing_vm_stat *)payload;
@@ -90,11 +99,11 @@ int physical_channel_send(struct physical_channel *pchan,
void physical_channel_rx_dispatch(unsigned long physical_channel)
{
- struct hab_header header;
+ struct hab_header header = {0};
struct physical_channel *pchan =
(struct physical_channel *)physical_channel;
struct ghs_vdev *dev = (struct ghs_vdev *)pchan->hyp_data;
- GIPC_Result result;
+ GIPC_Result result = GIPC_Success;
uint32_t events;
unsigned long flags;
@@ -119,7 +128,7 @@ void physical_channel_rx_dispatch(unsigned long physical_channel)
dev->read_data,
GIPC_RECV_BUFF_SIZE_BYTES,
&dev->read_size,
- &header.id_type_size);
+ (uint32_t *)&header.id_type_size);
if (result == GIPC_Success || dev->read_size > 0) {
/* handle corrupted msg? */
diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c
index b6dfe2d9ae22..f4fef27aeee1 100644
--- a/drivers/soc/qcom/hab/hab.c
+++ b/drivers/soc/qcom/hab/hab.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -21,7 +21,7 @@
.openlock = __SPIN_LOCK_UNLOCKED(&hab_devices[__num__].openlock)\
}
-static const char hab_info_str[] = "Change: 17280941 Revision: #81";
+static const char hab_info_str[] = "Change: 19231400 Revision: #95";
/*
* The following has to match habmm definitions, order does not matter if
@@ -60,7 +60,7 @@ struct hab_driver hab_driver = {
struct uhab_context *hab_ctx_alloc(int kernel)
{
- struct uhab_context *ctx;
+ struct uhab_context *ctx = NULL;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -79,6 +79,9 @@ struct uhab_context *hab_ctx_alloc(int kernel)
rwlock_init(&ctx->exp_lock);
rwlock_init(&ctx->ctx_lock);
+ INIT_LIST_HEAD(&ctx->forbidden_chans);
+ spin_lock_init(&ctx->forbidden_lock);
+
INIT_LIST_HEAD(&ctx->pending_open);
kref_init(&ctx->refcount);
ctx->import_ctx = habmem_imp_hyp_open();
@@ -106,18 +109,29 @@ void hab_ctx_free(struct kref *ref)
{
struct uhab_context *ctx =
container_of(ref, struct uhab_context, refcount);
- struct hab_export_ack_recvd *ack_recvd, *tmp;
- struct virtual_channel *vchan;
- struct physical_channel *pchan;
- int i;
- struct uhab_context *ctxdel, *ctxtmp;
- struct hab_open_node *node;
- struct export_desc *exp, *exp_tmp;
+ struct hab_export_ack_recvd *ack_recvd = NULL, *tmp = NULL;
+ struct virtual_channel *vchan = NULL;
+ struct physical_channel *pchan = NULL;
+ int i = 0;
+ struct uhab_context *ctxdel = NULL, *ctxtmp = NULL;
+ struct hab_open_node *node = NULL;
+ struct export_desc *exp = NULL, *exp_tmp = NULL;
+ struct hab_forbidden_node *forbidden = NULL, *forbidden_tmp = NULL;
+
+ spin_lock_bh(&ctx->forbidden_lock);
+ list_for_each_entry_safe(forbidden, forbidden_tmp,
+ &ctx->forbidden_chans, node) {
+ list_del(&forbidden->node);
+ pr_debug("Remove mmid 0x%x from forbidden list, ctx %p\n",
+ forbidden->mmid, ctx);
+ kfree(forbidden);
+ }
+ spin_unlock_bh(&ctx->forbidden_lock);
/* garbage-collect exp/imp buffers */
write_lock_bh(&ctx->exp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->exp_whse, node) {
- list_del(&exp->node);
+ list_del((struct list_head *)&exp->node);
pr_debug("potential leak exp %d vcid %X recovered\n",
exp->export_id, exp->vcid_local);
habmem_hyp_revoke(exp->payload, exp->payload_count);
@@ -127,7 +141,7 @@ void hab_ctx_free(struct kref *ref)
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->imp_whse, node) {
- list_del(&exp->node);
+ list_del((struct list_head *)&exp->node);
ctx->import_total--;
pr_debug("leaked imp %d vcid %X for ctx is collected total %d\n",
exp->export_id, exp->vcid_local,
@@ -211,7 +225,7 @@ void hab_ctx_free(struct kref *ref)
struct virtual_channel *hab_get_vchan_fromvcid(int32_t vcid,
struct uhab_context *ctx, int ignore_remote)
{
- struct virtual_channel *vchan;
+ struct virtual_channel *vchan = NULL;
read_lock(&ctx->ctx_lock);
list_for_each_entry(vchan, &ctx->vchannels, node) {
@@ -236,7 +250,7 @@ struct virtual_channel *hab_get_vchan_fromvcid(int32_t vcid,
struct hab_device *find_hab_device(unsigned int mm_id)
{
- int i;
+ int i = 0;
for (i = 0; i < hab_driver.ndevices; i++) {
if (hab_driver.devp[i].id == HAB_MMID_GET_MAJOR(mm_id))
@@ -259,13 +273,13 @@ struct virtual_channel *frontend_open(struct uhab_context *ctx,
unsigned int mm_id,
int dom_id)
{
- int ret, ret2, open_id = 0;
+ int ret = 0, ret2 = 0, open_id = 0;
struct physical_channel *pchan = NULL;
- struct hab_device *dev;
+ struct hab_device *dev = NULL;
struct virtual_channel *vchan = NULL;
static atomic_t open_id_counter = ATOMIC_INIT(0);
- struct hab_open_request request;
- struct hab_open_request *recv_request;
+ struct hab_open_request request = {0};
+ struct hab_open_request *recv_request = NULL;
int sub_id = HAB_MMID_GET_MINOR(mm_id);
struct hab_open_node pending_open = { { 0 } };
@@ -284,7 +298,7 @@ struct virtual_channel *frontend_open(struct uhab_context *ctx,
goto err;
}
- open_id = atomic_inc_return(&open_id_counter);
+ open_id = (int)atomic_inc_return(&open_id_counter);
vchan = hab_vchan_alloc(ctx, pchan, open_id);
if (!vchan) {
pr_err("vchan alloc failed\n");
@@ -336,7 +350,7 @@ struct virtual_channel *frontend_open(struct uhab_context *ctx,
vchan->id);
hab_open_pending_exit(ctx, pchan, &pending_open);
- if (ret != -EINTR)
+ if (ret != -EINTR && ret != -ENXIO)
ret = -EINVAL;
goto err;
}
@@ -377,15 +391,15 @@ err:
struct virtual_channel *backend_listen(struct uhab_context *ctx,
unsigned int mm_id, int timeout)
{
- int ret, ret2;
- int open_id, ver_fe;
+ int ret = 0, ret2 = 0;
+ int open_id = 0, ver_fe = 0;
int sub_id = HAB_MMID_GET_MINOR(mm_id);
struct physical_channel *pchan = NULL;
- struct hab_device *dev;
+ struct hab_device *dev = NULL;
struct virtual_channel *vchan = NULL;
- struct hab_open_request request;
- struct hab_open_request *recv_request;
- uint32_t otherend_vchan_id;
+ struct hab_open_request request = {0};
+ struct hab_open_request *recv_request = NULL;
+ uint32_t otherend_vchan_id = 0;
struct hab_open_node pending_open = { { 0 } };
dev = find_hab_device(mm_id);
@@ -407,6 +421,8 @@ struct virtual_channel *backend_listen(struct uhab_context *ctx,
ret = -EINVAL;
if (-EAGAIN == ret) {
ret = -ETIMEDOUT;
+ } else if (-ENXIO == ret) {
+ pr_warn("open request canceling\n");
} else {
/* device is closed */
pr_err("open request wait failed ctx closing %d\n",
@@ -416,7 +432,7 @@ struct virtual_channel *backend_listen(struct uhab_context *ctx,
} else if (!ret && recv_request &&
((recv_request->xdata.ver_fe & 0xFFFF0000) !=
(HAB_API_VER & 0xFFFF0000))) {
- int ret2;
+ int ret2 = 0;
/* version check */
pr_err("version mismatch fe %X be %X on mmid %d\n",
recv_request->xdata.ver_fe, HAB_API_VER, mm_id);
@@ -467,11 +483,11 @@ struct virtual_channel *backend_listen(struct uhab_context *ctx,
hab_open_request_init(&request, HAB_PAYLOAD_TYPE_INIT_DONE,
pchan, 0, sub_id, open_id);
ret = hab_open_listen(ctx, dev, &request, &recv_request,
- HAB_HS_TIMEOUT);
+ HAB_HS_INIT_DONE_TIMEOUT);
hab_open_pending_exit(ctx, pchan, &pending_open);
- if (ret && recv_request &&
+ if (!ret && recv_request &&
recv_request->type == HAB_PAYLOAD_TYPE_INIT_CANCEL) {
- pr_err("listen cancelled vcid %x subid %d openid %d ret %d\n",
+ pr_warn("open rmt cancelled vcid %x subid %d openid %d ret %d\n",
request.xdata.vchan_id, request.xdata.sub_id,
request.xdata.open_id, ret);
@@ -487,9 +503,12 @@ struct virtual_channel *backend_listen(struct uhab_context *ctx,
ret2, vchan->id);
hab_open_pending_exit(ctx, pchan, &pending_open);
- ret = -ENODEV; /* open request cancelled remotely */
+ ret = -ENODEV; /* open request FE cancelled remotely */
break;
- } else if (ret != -EAGAIN) {
+ } else if (-ENXIO == ret) {
+ pr_warn("backend mmid %d listen canceling\n", mm_id);
+ goto err;
+ } else if (ret != -EAGAIN && ret != -EINTR) {
hab_open_pending_exit(ctx, pchan, &pending_open);
break; /* received something. good case! */
}
@@ -540,8 +559,8 @@ long hab_vchan_send(struct uhab_context *ctx,
void *data,
unsigned int flags)
{
- struct virtual_channel *vchan;
- int ret;
+ struct virtual_channel *vchan = NULL;
+ int ret = 0;
struct hab_header header = HAB_HEADER_INITIALIZER;
int nonblocking_flag = flags & HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING;
@@ -557,7 +576,7 @@ long hab_vchan_send(struct uhab_context *ctx,
goto err;
}
- HAB_HEADER_SET_SIZE(header, sizebytes);
+ HAB_HEADER_SET_SIZE(header, (uint32_t)sizebytes);
if (flags & HABMM_SOCKET_SEND_FLAGS_XING_VM_STAT) {
HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_PROFILE);
if (sizebytes < sizeof(struct habmm_xing_vm_stat)) {
@@ -602,11 +621,11 @@ int hab_vchan_recv(struct uhab_context *ctx,
int *rsize,
unsigned int flags)
{
- struct virtual_channel *vchan;
+ struct virtual_channel *vchan = NULL;
int ret = 0;
int nonblocking_flag = flags & HABMM_SOCKET_RECV_FLAGS_NON_BLOCKING;
- vchan = hab_get_vchan_fromvcid(vcid, ctx, 1);
+ vchan = hab_get_vchan_fromvcid(vcid, ctx, 1); /* to drain local q */
if (!vchan) {
pr_err("vcid %X vchan 0x%pK ctx %pK\n", vcid, vchan, ctx);
return -ENODEV;
@@ -640,6 +659,68 @@ bool hab_is_loopback(void)
return hab_driver.b_loopback;
}
+static int hab_stop(struct uhab_context *ctx, unsigned int mmid)
+{
+ struct hab_forbidden_node *node = NULL, *tmp = NULL;
+ struct hab_device *dev = NULL;
+
+ dev = find_hab_device(mmid);
+ if (dev == NULL) {
+ pr_err("failed to find dev based on id 0x%x\n", mmid);
+ return -EINVAL;
+ }
+
+ spin_lock_bh(&ctx->forbidden_lock);
+
+ list_for_each_entry_safe(node, tmp, &ctx->forbidden_chans, node) {
+ if (node->mmid == mmid) {
+ pr_info("mmid 0x%x has been in forbidden list, ctx %p\n",
+ mmid, ctx);
+ spin_unlock_bh(&ctx->forbidden_lock);
+ return 0;
+ }
+ }
+
+ pr_info("Add mmid 0x%x into forbidden list, ctx %p\n",
+ mmid, ctx);
+
+ node = kzalloc(sizeof(*node), GFP_ATOMIC);
+ if (!node) {
+ spin_unlock_bh(&ctx->forbidden_lock);
+ return -ENOMEM;
+ }
+ node->mmid = mmid;
+ list_add_tail(&node->node, &ctx->forbidden_chans);
+
+ spin_unlock_bh(&ctx->forbidden_lock);
+
+ wake_up_interruptible(&dev->openq);
+
+ return 0;
+}
+
+int hab_is_forbidden(struct uhab_context *ctx,
+ struct hab_device *dev,
+ uint32_t sub_id)
+{
+ struct hab_forbidden_node *node = NULL, *tmp = NULL;
+
+ if (!dev)
+ return 0;
+
+ spin_lock_bh(&ctx->forbidden_lock);
+ list_for_each_entry_safe(node, tmp, &ctx->forbidden_chans, node) {
+ if ((HAB_MMID_GET_MAJOR(node->mmid) == dev->id) &&
+ (HAB_MMID_GET_MINOR(node->mmid) == sub_id)) {
+ spin_unlock_bh(&ctx->forbidden_lock);
+ return 1;
+ }
+ }
+ spin_unlock_bh(&ctx->forbidden_lock);
+
+ return 0;
+}
+
int hab_vchan_open(struct uhab_context *ctx,
unsigned int mmid,
int32_t *vcid,
@@ -647,8 +728,9 @@ int hab_vchan_open(struct uhab_context *ctx,
uint32_t flags)
{
struct virtual_channel *vchan = NULL;
- struct hab_device *dev;
+ struct hab_device *dev = NULL;
+ (void)flags;
pr_debug("Open mmid=%d, loopback mode=%d, loopback be ctx %d\n",
mmid, hab_driver.b_loopback, ctx->lb_be);
@@ -664,6 +746,13 @@ int hab_vchan_open(struct uhab_context *ctx,
} else {
dev = find_hab_device(mmid);
+ if (hab_is_forbidden(ctx,
+ dev, HAB_MMID_GET_MINOR(mmid))) {
+ pr_err("mmid 0x%x has been forbidden",
+ mmid);
+ return -ENXIO;
+ }
+
if (dev) {
struct physical_channel *pchan =
hab_pchan_find_domid(dev,
@@ -689,7 +778,7 @@ int hab_vchan_open(struct uhab_context *ctx,
if (IS_ERR(vchan)) {
if (-ETIMEDOUT != PTR_ERR(vchan) && -EAGAIN != PTR_ERR(vchan))
pr_err("vchan open failed mmid=%d\n", mmid);
- return PTR_ERR(vchan);
+ return (int)PTR_ERR(vchan);
}
pr_debug("vchan id %x remote id %x session %d\n", vchan->id,
@@ -720,7 +809,8 @@ void hab_send_close_msg(struct virtual_channel *vchan)
void hab_vchan_close(struct uhab_context *ctx, int32_t vcid)
{
- struct virtual_channel *vchan, *tmp;
+ struct virtual_channel *vchan = NULL, *tmp = NULL;
+ int vchan_found = 0;
if (!ctx)
return;
@@ -744,10 +834,14 @@ void hab_vchan_close(struct uhab_context *ctx, int32_t vcid)
hab_vchan_stop_notify(vchan);
hab_vchan_put(vchan); /* there is a lock inside */
write_lock(&ctx->ctx_lock);
+ vchan_found = 1;
break;
}
}
write_unlock(&ctx->ctx_lock);
+
+ if (!vchan_found)
+ hab_stop(ctx, vcid);
}
/*
@@ -760,9 +854,9 @@ void hab_vchan_close(struct uhab_context *ctx, int32_t vcid)
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];
+ char pchan_name[MAX_VMID_NAME_SIZE] = {0};
struct physical_channel *pchan = NULL;
- int ret;
+ int ret = 0;
int vmid = is_be ? vmid_remote : vmid_local; /* used for naming only */
if (!mmid_device) {
@@ -799,7 +893,7 @@ static int hab_initialize_pchan_entry(struct hab_device *mmid_device,
*/
static int hab_generate_pchan(struct local_vmid *settings, int i, int j)
{
- int k, ret = 0;
+ int k = 0, ret = 0;
pr_debug("%d as mmid %d in vmid %d\n",
HABCFG_GET_MMID(settings, i, j), j, i);
@@ -922,13 +1016,13 @@ static int hab_generate_pchan(struct local_vmid *settings, int i, int j)
*/
static int hab_generate_pchan_list(struct local_vmid *settings)
{
- int i, j, ret = 0;
+ int i = 0, j = 0, ret = 0;
/* 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) {
+ 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++) {
@@ -954,9 +1048,9 @@ static int hab_generate_pchan_list(struct local_vmid *settings)
int do_hab_parse(void)
{
- int result;
- int i;
- struct hab_device *device;
+ int result = 0;
+ int i = 0;
+ struct hab_device *device = NULL;
/* single GVM is 2, multigvm is 2 or 3. GHS LV-GVM 2, LA-GVM 3 */
int default_gvmid = DEFAULT_GVMID;
@@ -966,7 +1060,8 @@ int do_hab_parse(void)
/* 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);
+ pr_err("register HYP plug-in failed, ret %d driver version %s\n",
+ result, hab_info_str);
return result;
}
@@ -1014,13 +1109,13 @@ int get_refcnt(struct kref ref)
void hab_hypervisor_unregister_common(void)
{
- int status, i;
- struct uhab_context *ctx;
- struct virtual_channel *vchan;
+ int status = 0, i = 0;
+ struct uhab_context *ctx = NULL;
+ struct virtual_channel *vchan = NULL;
for (i = 0; i < hab_driver.ndevices; i++) {
struct hab_device *habdev = &hab_driver.devp[i];
- struct physical_channel *pchan, *pchan_tmp;
+ struct physical_channel *pchan = NULL, *pchan_tmp = NULL;
list_for_each_entry_safe(pchan, pchan_tmp,
&habdev->pchannels, node) {
@@ -1194,13 +1289,11 @@ static long hab_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
recv_param->sizebytes = 0;
ret = -EFAULT;
}
- } else if (ret && msg) {
- pr_warn("vcid %X recv failed %d and msg is still of %zd bytes\n",
- recv_param->vcid, (int)ret, msg->sizebytes);
- }
-
- if (msg)
hab_msg_free(msg);
+ } else
+ pr_warn("vcid %X recv failed %d buf size %d\n",
+ recv_param->vcid, (int)ret,
+ recv_param->sizebytes);
break;
case IOCTL_HAB_VC_EXPORT:
ret = hab_mem_export(ctx, (struct hab_export *)data, 0);
diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h
index 7d0c5f2673a2..cb7ed52050b2 100644
--- a/drivers/soc/qcom/hab/hab.h
+++ b/drivers/soc/qcom/hab/hab.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -46,6 +46,7 @@
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/delay.h>
+#include <linux/version.h>
#include <soc/qcom/boot_stats.h>
enum hab_payload_type {
@@ -161,13 +162,13 @@ struct hab_header {
#define HAB_HEADER_SET_SIZE(header, size) \
((header).id_type_size = ((header).id_type_size & \
- (~HAB_HEADER_SIZE_MASK)) | \
+ (uint32_t)(~HAB_HEADER_SIZE_MASK)) | \
(((size) << HAB_HEADER_SIZE_SHIFT) & \
HAB_HEADER_SIZE_MASK))
#define HAB_HEADER_SET_TYPE(header, type) \
((header).id_type_size = ((header).id_type_size & \
- (~HAB_HEADER_TYPE_MASK)) | \
+ (uint32_t)(~HAB_HEADER_TYPE_MASK)) | \
(((type) << HAB_HEADER_TYPE_SHIFT) & \
HAB_HEADER_TYPE_MASK))
@@ -192,6 +193,7 @@ struct hab_header {
#define HAB_HEADER_GET_SESSION_ID(header) ((header).session_id)
#define HAB_HS_TIMEOUT (10*1000*1000)
+#define HAB_HS_INIT_DONE_TIMEOUT (3*1000)
struct physical_channel {
struct list_head node;
@@ -265,6 +267,11 @@ struct hab_message {
uint32_t data[];
};
+struct hab_forbidden_node {
+ struct list_head node;
+ uint32_t mmid;
+};
+
/* for all the pchans of same kind */
struct hab_device {
char name[MAX_VMID_NAME_SIZE];
@@ -302,6 +309,9 @@ struct uhab_context {
struct list_head pending_open; /* sent to remote */
int pending_cnt;
+ struct list_head forbidden_chans;
+ spinlock_t forbidden_lock;
+
rwlock_t ctx_lock;
int closing;
int kernel;
@@ -403,6 +413,9 @@ struct export_desc {
unsigned char payload[1];
} __packed;
+int hab_is_forbidden(struct uhab_context *ctx,
+ struct hab_device *dev,
+ uint32_t sub_id);
int hab_vchan_open(struct uhab_context *ctx,
unsigned int mmid, int32_t *vcid,
int32_t timeout, uint32_t flags);
@@ -521,7 +534,7 @@ static inline void hab_ctx_get(struct uhab_context *ctx)
static inline void hab_ctx_put(struct uhab_context *ctx)
{
if (ctx)
- kref_put(&ctx->refcount, hab_ctx_free);
+ kref_put(&ctx->refcount, &hab_ctx_free);
}
void hab_send_close_msg(struct virtual_channel *vchan);
diff --git a/drivers/soc/qcom/hab/hab_ghs.c b/drivers/soc/qcom/hab/hab_ghs.c
index a445aa1a6707..01f42b5f67ac 100644
--- a/drivers/soc/qcom/hab/hab_ghs.c
+++ b/drivers/soc/qcom/hab/hab_ghs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -93,7 +93,7 @@ static int get_dt_name_idx(int vmid_base, int mmid,
struct ghs_vmm_plugin_info_s *plugin_info)
{
int idx = -1;
- int i;
+ int i = 0;
if (vmid_base < 0 || vmid_base > plugin_info->probe_cnt /
GIPC_VM_SET_CNT) {
diff --git a/drivers/soc/qcom/hab/hab_mem_linux.c b/drivers/soc/qcom/hab/hab_mem_linux.c
index 13bfab41f75d..6c61fbd00ded 100644
--- a/drivers/soc/qcom/hab/hab_mem_linux.c
+++ b/drivers/soc/qcom/hab/hab_mem_linux.c
@@ -598,6 +598,9 @@ static int hab_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
vma->vm_private_data = pglist;
vma->vm_flags |= VM_MIXEDMAP;
+ if (!(pglist->userflags & HABMM_IMPORT_FLAGS_CACHED))
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
return 0;
}
diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c
index b03739974390..c761099186d4 100644
--- a/drivers/soc/qcom/hab/hab_mimex.c
+++ b/drivers/soc/qcom/hab/hab_mimex.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,15 +31,14 @@ static int hab_export_ack_find(struct uhab_context *ctx,
struct hab_export_ack *expect_ack, struct virtual_channel *vchan)
{
int ret = 0;
- struct hab_export_ack_recvd *ack_recvd, *tmp;
+ struct hab_export_ack_recvd *ack_recvd = NULL, *tmp = NULL;
spin_lock_bh(&ctx->expq_lock);
list_for_each_entry_safe(ack_recvd, tmp, &ctx->exp_rxq, node) {
- if ((ack_recvd->ack.export_id == expect_ack->export_id &&
+ if (ack_recvd->ack.export_id == expect_ack->export_id &&
ack_recvd->ack.vcid_local == expect_ack->vcid_local &&
- ack_recvd->ack.vcid_remote == expect_ack->vcid_remote)
- || vchan->otherend_closed) {
+ ack_recvd->ack.vcid_remote == expect_ack->vcid_remote) {
list_del(&ack_recvd->node);
kfree(ack_recvd);
ret = 1;
@@ -52,6 +51,12 @@ static int hab_export_ack_find(struct uhab_context *ctx,
}
}
+ if (!ret && vchan->otherend_closed) {
+ pr_info("no expected ack, but vchan %x is remotely closed\n",
+ vchan->id);
+ ret = 1;
+ }
+
spin_unlock_bh(&ctx->expq_lock);
return ret;
@@ -60,7 +65,7 @@ static int hab_export_ack_find(struct uhab_context *ctx,
static int hab_export_ack_wait(struct uhab_context *ctx,
struct hab_export_ack *expect_ack, struct virtual_channel *vchan)
{
- int ret;
+ int ret = 0;
ret = wait_event_interruptible_timeout(ctx->exp_wq,
hab_export_ack_find(ctx, expect_ack, vchan),
@@ -83,8 +88,8 @@ static struct export_desc *habmem_add_export(struct virtual_channel *vchan,
int sizebytes,
uint32_t flags)
{
- struct uhab_context *ctx;
- struct export_desc *exp;
+ struct uhab_context *ctx = NULL;
+ struct export_desc *exp = NULL;
if (!vchan || !sizebytes)
return NULL;
@@ -112,7 +117,7 @@ static struct export_desc *habmem_add_export(struct virtual_channel *vchan,
ctx = vchan->ctx;
write_lock(&ctx->exp_lock);
ctx->export_total++;
- list_add_tail(&exp->node, &ctx->exp_whse);
+ list_add_tail((struct list_head *)&exp->node, &ctx->exp_whse);
write_unlock(&ctx->exp_lock);
return exp;
@@ -120,8 +125,8 @@ static struct export_desc *habmem_add_export(struct virtual_channel *vchan,
void habmem_remove_export(struct export_desc *exp)
{
- struct physical_channel *pchan;
- struct uhab_context *ctx;
+ struct physical_channel *pchan = NULL;
+ struct uhab_context *ctx = NULL;
if (!exp || !exp->ctx || !exp->pchan) {
if (exp)
@@ -146,7 +151,7 @@ void habmem_remove_export(struct export_desc *exp)
static int compress_pfns(void **pfns, int npages, unsigned int *data_size)
{
- int i, j = 0;
+ int i = 0, j = 0;
struct grantable *item = (struct grantable *)*pfns;
int region_size = 1;
struct compressed_pfns *new_table =
@@ -162,8 +167,8 @@ static int compress_pfns(void **pfns, int npages, unsigned int *data_size)
region_size++; /* continuous pfn */
} else {
new_table->region[j].size = region_size;
- new_table->region[j].space = item[i].pfn -
- item[i-1].pfn - 1;
+ new_table->region[j].space = (int)(item[i].pfn -
+ item[i-1].pfn - 1);
j++;
region_size = 1;
}
@@ -173,8 +178,8 @@ static int compress_pfns(void **pfns, int npages, unsigned int *data_size)
new_table->nregions = j+1;
vfree(*pfns);
- *data_size = sizeof(struct compressed_pfns) +
- sizeof(struct region)*new_table->nregions;
+ *data_size = (int)(sizeof(struct compressed_pfns) +
+ sizeof(struct region)*new_table->nregions);
*pfns = new_table;
return 0;
}
@@ -191,9 +196,9 @@ static int habmem_export_vchan(struct uhab_context *ctx,
int nunits,
uint32_t flags,
uint32_t *export_id) {
- int ret;
- struct export_desc *exp;
- uint32_t sizebytes = sizeof(*exp) + payload_size;
+ int ret = 0;
+ struct export_desc *exp = NULL;
+ uint32_t sizebytes = (uint32_t)(sizeof(*exp) + payload_size);
struct hab_export_ack expected_ack = {0};
struct hab_header header = HAB_HEADER_INITIALIZER;
@@ -239,8 +244,8 @@ int hab_mem_export(struct uhab_context *ctx,
void *pdata_exp = NULL;
unsigned int pdata_size = 0;
uint32_t export_id = 0;
- struct virtual_channel *vchan;
- int page_count;
+ struct virtual_channel *vchan = NULL;
+ int page_count = 0;
int compressed = 0;
if (!ctx || !param || !param->buffer)
@@ -266,7 +271,7 @@ int hab_mem_export(struct uhab_context *ctx,
vchan->pchan->dom_id,
pdata_exp,
&compressed,
- &pdata_size);
+ (int *)&pdata_size);
} else {
ret = habmem_hyp_grant_user((unsigned long)param->buffer,
page_count,
@@ -274,7 +279,7 @@ int hab_mem_export(struct uhab_context *ctx,
vchan->pchan->dom_id,
pdata_exp,
&compressed,
- &pdata_size);
+ (int *)&pdata_size);
}
if (ret < 0) {
pr_err("habmem_hyp_grant vc %x failed size=%d ret=%d\n",
@@ -306,9 +311,10 @@ int hab_mem_unexport(struct uhab_context *ctx,
int kernel)
{
int ret = 0, found = 0;
- struct export_desc *exp, *tmp;
- struct virtual_channel *vchan;
+ struct export_desc *exp = NULL, *tmp = NULL;
+ struct virtual_channel *vchan = NULL;
+ (void)kernel;
if (!ctx || !param)
return -EINVAL;
@@ -322,8 +328,9 @@ int hab_mem_unexport(struct uhab_context *ctx,
write_lock(&ctx->exp_lock);
list_for_each_entry_safe(exp, tmp, &ctx->exp_whse, node) {
if (param->exportid == exp->export_id &&
- vchan->pchan == exp->pchan) {
- list_del(&exp->node);
+ vchan->pchan == exp->pchan &&
+ param->vcid == exp->vcid_local) {
+ list_del((struct list_head *)&exp->node);
found = 1;
break;
}
@@ -355,7 +362,7 @@ int hab_mem_import(struct uhab_context *ctx,
{
int ret = 0, found = 0;
struct export_desc *exp = NULL;
- struct virtual_channel *vchan;
+ struct virtual_channel *vchan = NULL;
if (!ctx || !param)
return -EINVAL;
@@ -368,8 +375,9 @@ int hab_mem_import(struct uhab_context *ctx,
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry(exp, &ctx->imp_whse, node) {
- if ((exp->export_id == param->exportid) &&
- (exp->pchan == vchan->pchan)) {
+ if (exp->export_id == param->exportid &&
+ exp->pchan == vchan->pchan &&
+ param->vcid == exp->vcid_local) {
found = 1;
break;
}
@@ -414,8 +422,8 @@ int hab_mem_unimport(struct uhab_context *ctx,
int kernel)
{
int ret = 0, found = 0;
- struct export_desc *exp = NULL, *exp_tmp;
- struct virtual_channel *vchan;
+ struct export_desc *exp = NULL, *exp_tmp = NULL;
+ struct virtual_channel *vchan = NULL;
if (!ctx || !param)
return -EINVAL;
@@ -430,9 +438,10 @@ int hab_mem_unimport(struct uhab_context *ctx,
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->imp_whse, node) {
if (exp->export_id == param->exportid &&
- exp->pchan == vchan->pchan) {
+ exp->pchan == vchan->pchan &&
+ param->vcid == exp->vcid_local) {
/* same pchan is expected here */
- list_del(&exp->node);
+ list_del((struct list_head *)&exp->node);
ctx->import_total--;
found = 1;
break;
diff --git a/drivers/soc/qcom/hab/hab_msg.c b/drivers/soc/qcom/hab/hab_msg.c
index e0f4970ce14e..dabffa0e856a 100644
--- a/drivers/soc/qcom/hab/hab_msg.c
+++ b/drivers/soc/qcom/hab/hab_msg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,7 +14,7 @@
static int hab_rx_queue_empty(struct virtual_channel *vchan)
{
- int ret;
+ int ret = 0;
spin_lock_bh(&vchan->rx_lock);
ret = list_empty(&vchan->rx_list);
@@ -25,11 +25,11 @@ static int hab_rx_queue_empty(struct virtual_channel *vchan)
static struct hab_message*
hab_msg_alloc(struct physical_channel *pchan, size_t sizebytes)
{
- struct hab_message *message;
+ struct hab_message *message = NULL;
if (sizebytes > HAB_HEADER_SIZE_MASK) {
- pr_err("pchan %s send size too large %zd\n",
- pchan->name, sizebytes);
+ pr_err("pchan %s send size too large %zd header %zd\n",
+ pchan->name, sizebytes, sizeof(*message));
return NULL;
}
@@ -81,16 +81,16 @@ hab_msg_dequeue(struct virtual_channel *vchan, struct hab_message **msg,
message = list_first_entry(&vchan->rx_list,
struct hab_message, node);
if (message) {
- if (*rsize >= message->sizebytes) {
+ if (*rsize >= (int)message->sizebytes) {
/* msg can be safely retrieved in full */
list_del(&message->node);
ret = 0;
- *rsize = message->sizebytes;
+ *rsize = (int)message->sizebytes;
} else {
pr_err("vcid %x rcv buf too small %d < %zd\n",
vchan->id, *rsize,
message->sizebytes);
- *rsize = message->sizebytes;
+ *rsize = (int)message->sizebytes;
message = NULL;
ret = -EOVERFLOW; /* come back again */
}
@@ -121,7 +121,7 @@ static int hab_export_enqueue(struct virtual_channel *vchan,
struct uhab_context *ctx = vchan->ctx;
spin_lock_bh(&ctx->imp_lock);
- list_add_tail(&exp->node, &ctx->imp_whse);
+ list_add_tail((struct list_head *)&exp->node, &ctx->imp_whse);
ctx->import_total++;
spin_unlock_bh(&ctx->imp_lock);
@@ -139,7 +139,7 @@ static int hab_send_export_ack(struct virtual_channel *vchan,
};
struct hab_header header = HAB_HEADER_INITIALIZER;
- HAB_HEADER_SET_SIZE(header, sizeof(exp_ack));
+ HAB_HEADER_SET_SIZE(header, (uint32_t)sizeof(exp_ack));
HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_EXPORT_ACK);
HAB_HEADER_SET_ID(header, exp->vcid_local);
HAB_HEADER_SET_SESSION_ID(header, vchan->session_id);
@@ -159,9 +159,9 @@ static int hab_receive_create_export_ack(struct physical_channel *pchan,
pr_err("exp ack size %zu is not as arrived %zu\n",
sizeof(ack_recvd->ack), sizebytes);
- if (sizebytes > HAB_HEADER_SIZE_MASK) {
- pr_err("pchan %s read size too large %zd\n",
- pchan->name, sizebytes);
+ if (sizebytes > sizeof(ack_recvd->ack)) {
+ pr_err("pchan %s read size too large %zd %zd\n",
+ pchan->name, sizebytes, sizeof(ack_recvd->ack));
return -EINVAL;
}
@@ -197,16 +197,15 @@ int hab_msg_recv(struct physical_channel *pchan,
struct hab_header *header)
{
int ret = 0;
- struct hab_message *message;
+ struct hab_message *message = NULL;
struct hab_device *dev = pchan->habdev;
size_t sizebytes = HAB_HEADER_GET_SIZE(*header);
uint32_t payload_type = HAB_HEADER_GET_TYPE(*header);
uint32_t vchan_id = HAB_HEADER_GET_ID(*header);
uint32_t session_id = HAB_HEADER_GET_SESSION_ID(*header);
struct virtual_channel *vchan = NULL;
- struct export_desc *exp_desc;
- struct timeval tv;
- unsigned long long rx_mpm_tv;
+ struct export_desc *exp_desc = NULL, exp_ack = {0};
+ struct timeval tv = {0};
/* get the local virtual channel if it isn't an open message */
if (payload_type != HAB_PAYLOAD_TYPE_INIT &&
@@ -296,8 +295,8 @@ int hab_msg_recv(struct physical_channel *pchan,
case HAB_PAYLOAD_TYPE_EXPORT:
if (sizebytes > HAB_HEADER_SIZE_MASK) {
- pr_err("%s exp size too large %zd\n",
- pchan->name, sizebytes);
+ pr_err("%s exp size too large %zd header %zd\n",
+ pchan->name, sizebytes, sizeof(*exp_desc));
break;
}
@@ -322,9 +321,12 @@ int hab_msg_recv(struct physical_channel *pchan,
exp_desc->domid_remote = pchan->vmid_remote;
exp_desc->domid_local = pchan->vmid_local;
exp_desc->pchan = pchan;
+ exp_ack = *exp_desc; /* preserve exporter's info for ack */
+ exp_desc->vcid_remote = exp_desc->vcid_local;
+ exp_desc->vcid_local = vchan->id;
- hab_export_enqueue(vchan, exp_desc);
- hab_send_export_ack(vchan, pchan, exp_desc);
+ hab_export_enqueue(vchan, exp_desc); /* for local use */
+ hab_send_export_ack(vchan, pchan, &exp_ack); /* ack exporter */
break;
case HAB_PAYLOAD_TYPE_EXPORT_ACK:
diff --git a/drivers/soc/qcom/hab/hab_open.c b/drivers/soc/qcom/hab/hab_open.c
index bc2b774883f4..72dc9a54d20e 100644
--- a/drivers/soc/qcom/hab/hab_open.c
+++ b/drivers/soc/qcom/hab/hab_open.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -32,7 +32,8 @@ int hab_open_request_send(struct hab_open_request *request)
{
struct hab_header header = HAB_HEADER_INITIALIZER;
- HAB_HEADER_SET_SIZE(header, sizeof(struct hab_open_send_data));
+ HAB_HEADER_SET_SIZE(header,
+ (uint32_t)sizeof(struct hab_open_send_data));
HAB_HEADER_SET_TYPE(header, request->type);
return physical_channel_send(request->pchan, &header, &request->xdata);
@@ -42,12 +43,12 @@ int hab_open_request_send(struct hab_open_request *request)
int hab_open_request_add(struct physical_channel *pchan,
size_t sizebytes, int request_type)
{
- struct hab_open_node *node;
+ struct hab_open_node *node = NULL;
struct hab_device *dev = pchan->habdev;
- struct hab_open_request *request;
- struct timeval tv;
+ struct hab_open_request *request = NULL;
+ struct timeval tv = {0};
- if (sizebytes > HAB_HEADER_SIZE_MASK) {
+ if (sizebytes > sizeof(request->xdata)) {
pr_err("pchan %s request size too large %zd\n",
pchan->name, sizebytes);
return -EINVAL;
@@ -83,9 +84,9 @@ static int hab_open_request_find(struct uhab_context *ctx,
struct hab_open_request *listen,
struct hab_open_request **recv_request)
{
- struct hab_open_node *node, *tmp;
- struct hab_open_request *request;
- struct timeval tv;
+ struct hab_open_node *node = NULL, *tmp = NULL;
+ struct hab_open_request *request = NULL;
+ struct timeval tv = {0};
int ret = 0;
if (ctx->closing ||
@@ -126,6 +127,10 @@ static int hab_open_request_find(struct uhab_context *ctx,
done:
spin_unlock_bh(&dev->openlock);
+
+ if (hab_is_forbidden(ctx, dev, listen->xdata.sub_id))
+ ret = 1;
+
return ret;
}
@@ -165,6 +170,9 @@ int hab_open_listen(struct uhab_context *ctx,
pr_warn("something failed in open listen ret %d\n",
ret);
ret = -EINTR; /* condition not met */
+ } else if (hab_is_forbidden(ctx, dev, listen->xdata.sub_id)) {
+ pr_warn("local open cancelled ret %d\n", ret);
+ ret = -ENXIO;
} else if (ret > 0)
ret = 0; /* condition met */
} else { /* fe case */
@@ -176,6 +184,9 @@ int hab_open_listen(struct uhab_context *ctx,
} else if (-ERESTARTSYS == ret) {
pr_warn("local interrupted ret %d\n", ret);
ret = -EINTR;
+ } else if (hab_is_forbidden(ctx, dev, listen->xdata.sub_id)) {
+ pr_warn("local open cancelled ret %d\n", ret);
+ ret = -ENXIO;
}
}
@@ -187,15 +198,15 @@ int hab_open_receive_cancel(struct physical_channel *pchan,
size_t sizebytes)
{
struct hab_device *dev = pchan->habdev;
- struct hab_open_send_data data;
- struct hab_open_request *request;
- struct hab_open_node *node, *tmp;
+ struct hab_open_send_data data = {0};
+ struct hab_open_request *request = NULL;
+ struct hab_open_node *node = NULL, *tmp = NULL;
int bfound = 0;
- struct timeval tv;
+ struct timeval tv = {0};
- if (sizebytes > HAB_HEADER_SIZE_MASK) {
- pr_err("pchan %s cancel size too large %zd\n",
- pchan->name, sizebytes);
+ if (sizebytes > sizeof(data)) {
+ pr_err("pchan %s cancel size too large %zd header %zd\n",
+ pchan->name, sizebytes, sizeof(data));
return -EINVAL;
}
@@ -260,7 +271,8 @@ int hab_open_cancel_notify(struct hab_open_request *request)
{
struct hab_header header = HAB_HEADER_INITIALIZER;
- HAB_HEADER_SET_SIZE(header, sizeof(struct hab_open_send_data));
+ HAB_HEADER_SET_SIZE(header,
+ (uint32_t)sizeof(struct hab_open_send_data));
HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_INIT_CANCEL);
return physical_channel_send(request->pchan, &header, &request->xdata);
@@ -270,6 +282,7 @@ int hab_open_pending_enter(struct uhab_context *ctx,
struct physical_channel *pchan,
struct hab_open_node *pending)
{
+ (void)pchan;
write_lock(&ctx->ctx_lock);
list_add_tail(&pending->node, &ctx->pending_open);
ctx->pending_cnt++;
@@ -282,9 +295,10 @@ int hab_open_pending_exit(struct uhab_context *ctx,
struct physical_channel *pchan,
struct hab_open_node *pending)
{
- struct hab_open_node *node, *tmp;
+ struct hab_open_node *node = NULL, *tmp = NULL;
int ret = -ENOENT;
+ (void)pchan;
write_lock(&ctx->ctx_lock);
list_for_each_entry_safe(node, tmp, &ctx->pending_open, node) {
if ((node->request.type == pending->request.type) &&
diff --git a/drivers/soc/qcom/hab/hab_parser.c b/drivers/soc/qcom/hab/hab_parser.c
index c332587e2b47..1c53877005a0 100644
--- a/drivers/soc/qcom/hab/hab_parser.c
+++ b/drivers/soc/qcom/hab/hab_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,7 +23,7 @@ static int fill_vmid_mmid_tbl(struct vmid_mmid_desc *tbl, int32_t vm_start,
int32_t mmid_range, int32_t be)
{
int ret = 0;
- int i, j;
+ int i = 0, j = 0;
for (i = vm_start; i < vm_start+vm_range; i++) {
tbl[i].vmid = i; /* set valid vmid value to make it usable */
@@ -43,6 +43,7 @@ static int fill_vmid_mmid_tbl(struct vmid_mmid_desc *tbl, int32_t vm_start,
void dump_settings(struct local_vmid *settings)
{
+ (void)settings;
pr_debug("self vmid is %d\n", settings->self);
}
@@ -152,7 +153,7 @@ static int hab_parse_dt(struct local_vmid *settings)
*/
int hab_parse(struct local_vmid *settings)
{
- int ret;
+ int ret = 0;
ret = hab_parse_dt(settings);
diff --git a/drivers/soc/qcom/hab/hab_pchan.c b/drivers/soc/qcom/hab/hab_pchan.c
index 8a9a6dfd1e0c..d82321a2b9cf 100644
--- a/drivers/soc/qcom/hab/hab_pchan.c
+++ b/drivers/soc/qcom/hab/hab_pchan.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -47,7 +47,7 @@ static void hab_pchan_free(struct kref *ref)
{
struct physical_channel *pchan =
container_of(ref, struct physical_channel, refcount);
- struct virtual_channel *vchan;
+ struct virtual_channel *vchan = NULL;
pr_debug("pchan %s refcnt %d\n", pchan->name,
get_refcnt(pchan->refcount));
@@ -67,14 +67,13 @@ static void hab_pchan_free(struct kref *ref)
}
read_unlock(&pchan->vchans_lock);
- kfree(pchan->hyp_data);
kfree(pchan);
}
struct physical_channel *
hab_pchan_find_domid(struct hab_device *dev, int dom_id)
{
- struct physical_channel *pchan;
+ struct physical_channel *pchan = NULL;
spin_lock_bh(&dev->pchan_lock);
list_for_each_entry(pchan, &dev->pchannels, node)
@@ -104,5 +103,5 @@ void hab_pchan_get(struct physical_channel *pchan)
void hab_pchan_put(struct physical_channel *pchan)
{
if (pchan)
- kref_put(&pchan->refcount, hab_pchan_free);
+ kref_put(&pchan->refcount, &hab_pchan_free);
}
diff --git a/drivers/soc/qcom/hab/hab_stat.c b/drivers/soc/qcom/hab/hab_stat.c
index b78e5e7e9867..b72528cc4d5f 100644
--- a/drivers/soc/qcom/hab/hab_stat.c
+++ b/drivers/soc/qcom/hab/hab_stat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -32,28 +32,28 @@ int hab_stat_deinit(struct hab_driver *driver)
static int hab_stat_buffer_print(char *dest,
int dest_size, const char *fmt, ...)
{
- va_list args;
- char line[MAX_LINE_SIZE];
- int ret;
+ va_list args = {0};
+ char line[MAX_LINE_SIZE] = {0};
+ int ret = 0;
va_start(args, fmt);
ret = vsnprintf(line, sizeof(line), fmt, args);
va_end(args);
if (ret > 0)
- ret = strlcat(dest, line, dest_size);
+ ret = (int)strlcat(dest, line, dest_size);
return ret;
}
int hab_stat_show_vchan(struct hab_driver *driver,
char *buf, int size)
{
- int i, ret = 0;
+ int i = 0, ret = 0;
- ret = strlcpy(buf, "", size);
+ ret = (int)strlcpy(buf, "", size);
for (i = 0; i < driver->ndevices; i++) {
struct hab_device *dev = &driver->devp[i];
- struct physical_channel *pchan;
- struct virtual_channel *vc;
+ struct physical_channel *pchan = NULL;
+ struct virtual_channel *vc = NULL;
spin_lock_bh(&dev->pchan_lock);
list_for_each_entry(pchan, &dev->pchannels, node) {
@@ -86,9 +86,9 @@ int hab_stat_show_ctx(struct hab_driver *driver,
char *buf, int size)
{
int ret = 0;
- struct uhab_context *ctx;
+ struct uhab_context *ctx = NULL;
- ret = strlcpy(buf, "", size);
+ ret = (int)strlcpy(buf, "", size);
spin_lock_bh(&hab_driver.drvlock);
ret = hab_stat_buffer_print(buf, size,
@@ -96,10 +96,11 @@ int hab_stat_show_ctx(struct hab_driver *driver,
driver->ctx_cnt);
list_for_each_entry(ctx, &hab_driver.uctx_list, node) {
ret = hab_stat_buffer_print(buf, size,
- "ctx %d K %d close %d vc %d exp %d imp %d open %d\n",
+ "ctx %d K %d close %d vc %d exp %d imp %d open %d ref %d\n",
ctx->owner, ctx->kernel, ctx->closing,
ctx->vcnt, ctx->export_total,
- ctx->import_total, ctx->pending_cnt);
+ ctx->import_total, ctx->pending_cnt,
+ get_refcnt(ctx->refcount));
}
spin_unlock_bh(&hab_driver.drvlock);
@@ -108,7 +109,7 @@ int hab_stat_show_ctx(struct hab_driver *driver,
static int get_pft_tbl_total_size(struct compressed_pfns *pfn_table)
{
- int i, total_size = 0;
+ int i = 0, total_size = 0;
for (i = 0; i < pfn_table->nregions; i++)
total_size += pfn_table->region[i].size * PAGE_SIZE;
@@ -119,27 +120,40 @@ static int get_pft_tbl_total_size(struct compressed_pfns *pfn_table)
static int print_ctx_total_expimp(struct uhab_context *ctx,
char *buf, int size)
{
- struct compressed_pfns *pfn_table;
+ struct compressed_pfns *pfn_table = NULL;
int exp_total = 0, imp_total = 0;
int exp_cnt = 0, imp_cnt = 0;
- struct export_desc *exp;
+ struct export_desc *exp = NULL;
+ int exim_size = 0;
read_lock(&ctx->exp_lock);
+ hab_stat_buffer_print(buf, size, "export[expid:vcid:size]: ");
list_for_each_entry(exp, &ctx->exp_whse, node) {
pfn_table = (struct compressed_pfns *)exp->payload;
- exp_total += get_pft_tbl_total_size(pfn_table);
+ exim_size = get_pft_tbl_total_size(pfn_table);
+ exp_total += exim_size;
exp_cnt++;
+ hab_stat_buffer_print(buf, size,
+ "[%d:%x:%d] ", exp->export_id,
+ exp->vcid_local, exim_size);
}
+ hab_stat_buffer_print(buf, size, "\n");
read_unlock(&ctx->exp_lock);
spin_lock_bh(&ctx->imp_lock);
+ hab_stat_buffer_print(buf, size, "import[expid:vcid:size]: ");
list_for_each_entry(exp, &ctx->imp_whse, node) {
if (habmm_imp_hyp_map_check(ctx->import_ctx, exp)) {
pfn_table = (struct compressed_pfns *)exp->payload;
- imp_total += get_pft_tbl_total_size(pfn_table);
+ exim_size = get_pft_tbl_total_size(pfn_table);
+ imp_total += exim_size;
imp_cnt++;
+ hab_stat_buffer_print(buf, size,
+ "[%d:%x:%d] ", exp->export_id,
+ exp->vcid_local, exim_size);
}
}
+ hab_stat_buffer_print(buf, size, "\n");
spin_unlock_bh(&ctx->imp_lock);
if (exp_cnt || exp_total || imp_cnt || imp_total)
@@ -154,10 +168,11 @@ static int print_ctx_total_expimp(struct uhab_context *ctx,
int hab_stat_show_expimp(struct hab_driver *driver,
int pid, char *buf, int size)
{
- struct uhab_context *ctx;
- int ret;
+ struct uhab_context *ctx = NULL;
+ int ret = 0;
- ret = strlcpy(buf, "", size);
+ (void)driver;
+ ret = (int)strlcpy(buf, "", size);
spin_lock_bh(&hab_driver.drvlock);
list_for_each_entry(ctx, &hab_driver.uctx_list, node) {
diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c
index a95d6c7451c9..a6ee00211347 100644
--- a/drivers/soc/qcom/hab/hab_vchan.c
+++ b/drivers/soc/qcom/hab/hab_vchan.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,8 +16,8 @@ struct virtual_channel *
hab_vchan_alloc(struct uhab_context *ctx, struct physical_channel *pchan,
int openid)
{
- int id;
- struct virtual_channel *vchan;
+ int id = 0;
+ struct virtual_channel *vchan = NULL;
if (!pchan || !ctx)
return NULL;
@@ -73,10 +73,10 @@ hab_vchan_free(struct kref *ref)
{
struct virtual_channel *vchan =
container_of(ref, struct virtual_channel, refcount);
- struct hab_message *message, *msg_tmp;
+ struct hab_message *message = NULL, *msg_tmp = NULL;
struct physical_channel *pchan = vchan->pchan;
struct uhab_context *ctx = vchan->ctx;
- struct virtual_channel *vc, *vc_tmp;
+ struct virtual_channel *vc = NULL, *vc_tmp = NULL;
spin_lock_bh(&vchan->rx_lock);
list_for_each_entry_safe(message, msg_tmp, &vchan->rx_list, node) {
@@ -117,7 +117,7 @@ hab_vchan_free(struct kref *ref)
struct virtual_channel*
hab_vchan_get(struct physical_channel *pchan, struct hab_header *header)
{
- struct virtual_channel *vchan;
+ struct virtual_channel *vchan = NULL;
uint32_t vchan_id = HAB_HEADER_GET_ID(*header);
uint32_t session_id = HAB_HEADER_GET_SESSION_ID(*header);
size_t sizebytes = HAB_HEADER_GET_SIZE(*header);
@@ -182,7 +182,7 @@ void hab_vchan_stop(struct virtual_channel *vchan)
void hab_vchans_stop(struct physical_channel *pchan)
{
- struct virtual_channel *vchan, *tmp;
+ struct virtual_channel *vchan = NULL, *tmp = NULL;
read_lock(&pchan->vchans_lock);
list_for_each_entry_safe(vchan, tmp, &pchan->vchannels, pnode) {
@@ -200,12 +200,12 @@ void hab_vchan_stop_notify(struct virtual_channel *vchan)
static int hab_vchans_per_pchan_empty(struct physical_channel *pchan)
{
- int empty;
+ int empty = 0;
read_lock(&pchan->vchans_lock);
empty = list_empty(&pchan->vchannels);
if (!empty) {
- struct virtual_channel *vchan;
+ struct virtual_channel *vchan = NULL;
int vcnt = pchan->vcnt;
list_for_each_entry(vchan, &pchan->vchannels, pnode) {
@@ -230,9 +230,9 @@ static int hab_vchans_per_pchan_empty(struct physical_channel *pchan)
static int hab_vchans_empty(int vmid)
{
- int i, empty = 1;
- struct physical_channel *pchan;
- struct hab_device *hab_dev;
+ int i = 0, empty = 1;
+ struct physical_channel *pchan = NULL;
+ struct hab_device *hab_dev = NULL;
for (i = 0; i < hab_driver.ndevices; i++) {
hab_dev = &hab_driver.devp[i];
@@ -277,13 +277,15 @@ int hab_vchan_find_domid(struct virtual_channel *vchan)
void hab_vchan_put(struct virtual_channel *vchan)
{
if (vchan)
- kref_put(&vchan->refcount, hab_vchan_free);
+ kref_put(&vchan->refcount, &hab_vchan_free);
}
int hab_vchan_query(struct uhab_context *ctx, int32_t vcid, uint64_t *ids,
char *names, size_t name_size, uint32_t flags)
{
- struct virtual_channel *vchan;
+ struct virtual_channel *vchan = NULL;
+
+ (void)flags;
vchan = hab_get_vchan_fromvcid(vcid, ctx, 1);
if (!vchan)
diff --git a/drivers/soc/qcom/hab/khab.c b/drivers/soc/qcom/hab/khab.c
index c4acf12fd553..b9b508e8e72d 100644
--- a/drivers/soc/qcom/hab/khab.c
+++ b/drivers/soc/qcom/hab/khab.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -47,7 +47,7 @@ int32_t habmm_socket_recv(int32_t handle, void *dst_buff, uint32_t *size_bytes,
uint32_t timeout, uint32_t flags)
{
int ret = 0;
- struct hab_message *msg;
+ struct hab_message *msg = NULL;
if (!size_bytes || !dst_buff)
return -EINVAL;