static int mon_check_mca(struct mon_msg *monmsg)
{
	if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
	    (mon_rec_start(monmsg) < mon_dcss_start) ||
	    (mon_rec_end(monmsg) > mon_dcss_end) ||
	    (mon_mca_type(monmsg, 0) == 0) ||
	    (mon_mca_size(monmsg) % 12 != 0) ||
	    (mon_mca_end(monmsg) <= mon_mca_start(monmsg)) ||
	    (mon_mca_end(monmsg) > mon_dcss_end) ||
	    (mon_mca_start(monmsg) < mon_dcss_start) ||
	    ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0)))
		return -EINVAL;
	return 0;
}
Example #2
0
static inline void mon_read_debug(struct mon_msg *monmsg,
                  struct mon_private *monpriv)
{
#ifdef MON_DEBUG
    u8 msg_type[2], mca_type;
    unsigned long records_len;

    records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;

    memcpy(msg_type, &monmsg->msg.class, 2);
    EBCASC(msg_type, 2);
    mca_type = mon_mca_type(monmsg, 0);
    EBCASC(&mca_type, 1);

    P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
        monpriv->read_index, monpriv->write_index);
    P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
        monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
    P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
        msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
        mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
    P_DEBUG("read, MCA: start = 0x%lX, end = 0x%lX\n",
        mon_mca_start(monmsg), mon_mca_end(monmsg));
    P_DEBUG("read, REC: start = 0x%X, end = 0x%X, len = %lu\n\n",
        mon_rec_start(monmsg), mon_rec_end(monmsg), records_len);
    if (mon_mca_size(monmsg) > 12)
        P_DEBUG("READ, MORE THAN ONE MCA\n\n");
#endif
}
Example #3
0
static int mon_check_mca(struct mon_msg *monmsg)
{
    if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
        (mon_rec_start(monmsg) < mon_dcss_start) ||
        (mon_rec_end(monmsg) > mon_dcss_end) ||
        (mon_mca_type(monmsg, 0) == 0) ||
        (mon_mca_size(monmsg) % 12 != 0) ||
        (mon_mca_end(monmsg) <= mon_mca_start(monmsg)) ||
        (mon_mca_end(monmsg) > mon_dcss_end) ||
        (mon_mca_start(monmsg) < mon_dcss_start) ||
        ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0)))
    {
        P_DEBUG("READ, IGNORED INVALID MCA\n\n");
        return -EINVAL;
    }
    return 0;
}
static ssize_t mon_read(struct file *filp, char __user *data,
			size_t count, loff_t *ppos)
{
	struct mon_private *monpriv = filp->private_data;
	struct mon_msg *monmsg;
	int ret;
	u32 mce_start;

	monmsg = mon_next_message(monpriv);
	if (IS_ERR(monmsg))
		return PTR_ERR(monmsg);

	if (!monmsg) {
		if (filp->f_flags & O_NONBLOCK)
			return -EAGAIN;
		ret = wait_event_interruptible(mon_read_wait_queue,
					atomic_read(&monpriv->read_ready) ||
					atomic_read(&monpriv->iucv_severed));
		if (ret)
			return ret;
		if (unlikely(atomic_read(&monpriv->iucv_severed)))
			return -EIO;
		monmsg = monpriv->msg_array[monpriv->read_index];
	}

	if (!monmsg->pos)
		monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset;
	if (mon_check_mca(monmsg))
		goto reply;

	/* read monitor control element (12 bytes) first */
	mce_start = mon_mca_start(monmsg) + monmsg->mca_offset;
	if ((monmsg->pos >= mce_start) && (monmsg->pos < mce_start + 12)) {
		count = min(count, (size_t) mce_start + 12 - monmsg->pos);
		ret = copy_to_user(data, (void *) (unsigned long) monmsg->pos,
				   count);
		if (ret)
			return -EFAULT;
		monmsg->pos += count;
		if (monmsg->pos == mce_start + 12)
			monmsg->pos = mon_rec_start(monmsg);
		goto out_copy;
	}

	/* read records */
	if (monmsg->pos <= mon_rec_end(monmsg)) {
		count = min(count, (size_t) mon_rec_end(monmsg) - monmsg->pos
					    + 1);
		ret = copy_to_user(data, (void *) (unsigned long) monmsg->pos,
				   count);
		if (ret)
			return -EFAULT;
		monmsg->pos += count;
		if (monmsg->pos > mon_rec_end(monmsg))
			mon_next_mca(monmsg);
		goto out_copy;
	}
reply:
	ret = mon_send_reply(monmsg, monpriv);
	return ret;

out_copy:
	*ppos += count;
	return count;
}
static inline u32 mon_rec_end(struct mon_msg *monmsg)
{
	return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
}
static inline u32 mon_mca_size(struct mon_msg *monmsg)
{
	return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;
}
static inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index)
{
	return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);
}