Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Character device driver for reading z/VM *MONITOR service records.
0004  *
0005  * Copyright IBM Corp. 2004, 2009
0006  *
0007  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
0008  */
0009 
0010 #define KMSG_COMPONENT "monreader"
0011 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0012 
0013 #include <linux/module.h>
0014 #include <linux/moduleparam.h>
0015 #include <linux/init.h>
0016 #include <linux/errno.h>
0017 #include <linux/types.h>
0018 #include <linux/kernel.h>
0019 #include <linux/miscdevice.h>
0020 #include <linux/ctype.h>
0021 #include <linux/spinlock.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/poll.h>
0024 #include <linux/slab.h>
0025 #include <net/iucv/iucv.h>
0026 #include <linux/uaccess.h>
0027 #include <asm/ebcdic.h>
0028 #include <asm/extmem.h>
0029 
0030 
0031 #define MON_COLLECT_SAMPLE 0x80
0032 #define MON_COLLECT_EVENT  0x40
0033 #define MON_SERVICE    "*MONITOR"
0034 #define MON_IN_USE     0x01
0035 #define MON_MSGLIM     255
0036 
0037 static char mon_dcss_name[9] = "MONDCSS\0";
0038 
0039 struct mon_msg {
0040     u32 pos;
0041     u32 mca_offset;
0042     struct iucv_message msg;
0043     char msglim_reached;
0044     char replied_msglim;
0045 };
0046 
0047 struct mon_private {
0048     struct iucv_path *path;
0049     struct mon_msg *msg_array[MON_MSGLIM];
0050     unsigned int   write_index;
0051     unsigned int   read_index;
0052     atomic_t msglim_count;
0053     atomic_t read_ready;
0054     atomic_t iucv_connected;
0055     atomic_t iucv_severed;
0056 };
0057 
0058 static unsigned long mon_in_use = 0;
0059 
0060 static unsigned long mon_dcss_start;
0061 static unsigned long mon_dcss_end;
0062 
0063 static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue);
0064 static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue);
0065 
0066 static u8 user_data_connect[16] = {
0067     /* Version code, must be 0x01 for shared mode */
0068     0x01,
0069     /* what to collect */
0070     MON_COLLECT_SAMPLE | MON_COLLECT_EVENT,
0071     /* DCSS name in EBCDIC, 8 bytes padded with blanks */
0072     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0073     0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0074 };
0075 
0076 static u8 user_data_sever[16] = {
0077     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0078     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0079 };
0080 
0081 /******************************************************************************
0082  *                             helper functions                               *
0083  *****************************************************************************/
0084 /*
0085  * Create the 8 bytes EBCDIC DCSS segment name from
0086  * an ASCII name, incl. padding
0087  */
0088 static void dcss_mkname(char *ascii_name, char *ebcdic_name)
0089 {
0090     int i;
0091 
0092     for (i = 0; i < 8; i++) {
0093         if (ascii_name[i] == '\0')
0094             break;
0095         ebcdic_name[i] = toupper(ascii_name[i]);
0096     }
0097     for (; i < 8; i++)
0098         ebcdic_name[i] = ' ';
0099     ASCEBC(ebcdic_name, 8);
0100 }
0101 
0102 static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
0103 {
0104     return *(u32 *) &monmsg->msg.rmmsg;
0105 }
0106 
0107 static inline unsigned long mon_mca_end(struct mon_msg *monmsg)
0108 {
0109     return *(u32 *) &monmsg->msg.rmmsg[4];
0110 }
0111 
0112 static inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index)
0113 {
0114     return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);
0115 }
0116 
0117 static inline u32 mon_mca_size(struct mon_msg *monmsg)
0118 {
0119     return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;
0120 }
0121 
0122 static inline u32 mon_rec_start(struct mon_msg *monmsg)
0123 {
0124     return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4));
0125 }
0126 
0127 static inline u32 mon_rec_end(struct mon_msg *monmsg)
0128 {
0129     return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
0130 }
0131 
0132 static int mon_check_mca(struct mon_msg *monmsg)
0133 {
0134     if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
0135         (mon_rec_start(monmsg) < mon_dcss_start) ||
0136         (mon_rec_end(monmsg) > mon_dcss_end) ||
0137         (mon_mca_type(monmsg, 0) == 0) ||
0138         (mon_mca_size(monmsg) % 12 != 0) ||
0139         (mon_mca_end(monmsg) <= mon_mca_start(monmsg)) ||
0140         (mon_mca_end(monmsg) > mon_dcss_end) ||
0141         (mon_mca_start(monmsg) < mon_dcss_start) ||
0142         ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0)))
0143         return -EINVAL;
0144     return 0;
0145 }
0146 
0147 static int mon_send_reply(struct mon_msg *monmsg,
0148               struct mon_private *monpriv)
0149 {
0150     int rc;
0151 
0152     rc = iucv_message_reply(monpriv->path, &monmsg->msg,
0153                 IUCV_IPRMDATA, NULL, 0);
0154     atomic_dec(&monpriv->msglim_count);
0155     if (likely(!monmsg->msglim_reached)) {
0156         monmsg->pos = 0;
0157         monmsg->mca_offset = 0;
0158         monpriv->read_index = (monpriv->read_index + 1) %
0159                       MON_MSGLIM;
0160         atomic_dec(&monpriv->read_ready);
0161     } else
0162         monmsg->replied_msglim = 1;
0163     if (rc) {
0164         pr_err("Reading monitor data failed with rc=%i\n", rc);
0165         return -EIO;
0166     }
0167     return 0;
0168 }
0169 
0170 static void mon_free_mem(struct mon_private *monpriv)
0171 {
0172     int i;
0173 
0174     for (i = 0; i < MON_MSGLIM; i++)
0175         kfree(monpriv->msg_array[i]);
0176     kfree(monpriv);
0177 }
0178 
0179 static struct mon_private *mon_alloc_mem(void)
0180 {
0181     int i;
0182     struct mon_private *monpriv;
0183 
0184     monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
0185     if (!monpriv)
0186         return NULL;
0187     for (i = 0; i < MON_MSGLIM; i++) {
0188         monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg),
0189                             GFP_KERNEL);
0190         if (!monpriv->msg_array[i]) {
0191             mon_free_mem(monpriv);
0192             return NULL;
0193         }
0194     }
0195     return monpriv;
0196 }
0197 
0198 static inline void mon_next_mca(struct mon_msg *monmsg)
0199 {
0200     if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
0201         return;
0202     monmsg->mca_offset += 12;
0203     monmsg->pos = 0;
0204 }
0205 
0206 static struct mon_msg *mon_next_message(struct mon_private *monpriv)
0207 {
0208     struct mon_msg *monmsg;
0209 
0210     if (!atomic_read(&monpriv->read_ready))
0211         return NULL;
0212     monmsg = monpriv->msg_array[monpriv->read_index];
0213     if (unlikely(monmsg->replied_msglim)) {
0214         monmsg->replied_msglim = 0;
0215         monmsg->msglim_reached = 0;
0216         monmsg->pos = 0;
0217         monmsg->mca_offset = 0;
0218         monpriv->read_index = (monpriv->read_index + 1) %
0219                       MON_MSGLIM;
0220         atomic_dec(&monpriv->read_ready);
0221         return ERR_PTR(-EOVERFLOW);
0222     }
0223     return monmsg;
0224 }
0225 
0226 
0227 /******************************************************************************
0228  *                               IUCV handler                                 *
0229  *****************************************************************************/
0230 static void mon_iucv_path_complete(struct iucv_path *path, u8 *ipuser)
0231 {
0232     struct mon_private *monpriv = path->private;
0233 
0234     atomic_set(&monpriv->iucv_connected, 1);
0235     wake_up(&mon_conn_wait_queue);
0236 }
0237 
0238 static void mon_iucv_path_severed(struct iucv_path *path, u8 *ipuser)
0239 {
0240     struct mon_private *monpriv = path->private;
0241 
0242     pr_err("z/VM *MONITOR system service disconnected with rc=%i\n",
0243            ipuser[0]);
0244     iucv_path_sever(path, NULL);
0245     atomic_set(&monpriv->iucv_severed, 1);
0246     wake_up(&mon_conn_wait_queue);
0247     wake_up_interruptible(&mon_read_wait_queue);
0248 }
0249 
0250 static void mon_iucv_message_pending(struct iucv_path *path,
0251                      struct iucv_message *msg)
0252 {
0253     struct mon_private *monpriv = path->private;
0254 
0255     memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
0256            msg, sizeof(*msg));
0257     if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
0258         pr_warn("The read queue for monitor data is full\n");
0259         monpriv->msg_array[monpriv->write_index]->msglim_reached = 1;
0260     }
0261     monpriv->write_index = (monpriv->write_index + 1) % MON_MSGLIM;
0262     atomic_inc(&monpriv->read_ready);
0263     wake_up_interruptible(&mon_read_wait_queue);
0264 }
0265 
0266 static struct iucv_handler monreader_iucv_handler = {
0267     .path_complete   = mon_iucv_path_complete,
0268     .path_severed    = mon_iucv_path_severed,
0269     .message_pending = mon_iucv_message_pending,
0270 };
0271 
0272 /******************************************************************************
0273  *                               file operations                              *
0274  *****************************************************************************/
0275 static int mon_open(struct inode *inode, struct file *filp)
0276 {
0277     struct mon_private *monpriv;
0278     int rc;
0279 
0280     /*
0281      * only one user allowed
0282      */
0283     rc = -EBUSY;
0284     if (test_and_set_bit(MON_IN_USE, &mon_in_use))
0285         goto out;
0286 
0287     rc = -ENOMEM;
0288     monpriv = mon_alloc_mem();
0289     if (!monpriv)
0290         goto out_use;
0291 
0292     /*
0293      * Connect to *MONITOR service
0294      */
0295     monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL);
0296     if (!monpriv->path)
0297         goto out_priv;
0298     rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler,
0299                    MON_SERVICE, NULL, user_data_connect, monpriv);
0300     if (rc) {
0301         pr_err("Connecting to the z/VM *MONITOR system service "
0302                "failed with rc=%i\n", rc);
0303         rc = -EIO;
0304         goto out_path;
0305     }
0306     /*
0307      * Wait for connection confirmation
0308      */
0309     wait_event(mon_conn_wait_queue,
0310            atomic_read(&monpriv->iucv_connected) ||
0311            atomic_read(&monpriv->iucv_severed));
0312     if (atomic_read(&monpriv->iucv_severed)) {
0313         atomic_set(&monpriv->iucv_severed, 0);
0314         atomic_set(&monpriv->iucv_connected, 0);
0315         rc = -EIO;
0316         goto out_path;
0317     }
0318     filp->private_data = monpriv;
0319     return nonseekable_open(inode, filp);
0320 
0321 out_path:
0322     iucv_path_free(monpriv->path);
0323 out_priv:
0324     mon_free_mem(monpriv);
0325 out_use:
0326     clear_bit(MON_IN_USE, &mon_in_use);
0327 out:
0328     return rc;
0329 }
0330 
0331 static int mon_close(struct inode *inode, struct file *filp)
0332 {
0333     int rc, i;
0334     struct mon_private *monpriv = filp->private_data;
0335 
0336     /*
0337      * Close IUCV connection and unregister
0338      */
0339     if (monpriv->path) {
0340         rc = iucv_path_sever(monpriv->path, user_data_sever);
0341         if (rc)
0342             pr_warn("Disconnecting the z/VM *MONITOR system service failed with rc=%i\n",
0343                 rc);
0344         iucv_path_free(monpriv->path);
0345     }
0346 
0347     atomic_set(&monpriv->iucv_severed, 0);
0348     atomic_set(&monpriv->iucv_connected, 0);
0349     atomic_set(&monpriv->read_ready, 0);
0350     atomic_set(&monpriv->msglim_count, 0);
0351     monpriv->write_index  = 0;
0352     monpriv->read_index   = 0;
0353 
0354     for (i = 0; i < MON_MSGLIM; i++)
0355         kfree(monpriv->msg_array[i]);
0356     kfree(monpriv);
0357     clear_bit(MON_IN_USE, &mon_in_use);
0358     return 0;
0359 }
0360 
0361 static ssize_t mon_read(struct file *filp, char __user *data,
0362             size_t count, loff_t *ppos)
0363 {
0364     struct mon_private *monpriv = filp->private_data;
0365     struct mon_msg *monmsg;
0366     int ret;
0367     u32 mce_start;
0368 
0369     monmsg = mon_next_message(monpriv);
0370     if (IS_ERR(monmsg))
0371         return PTR_ERR(monmsg);
0372 
0373     if (!monmsg) {
0374         if (filp->f_flags & O_NONBLOCK)
0375             return -EAGAIN;
0376         ret = wait_event_interruptible(mon_read_wait_queue,
0377                     atomic_read(&monpriv->read_ready) ||
0378                     atomic_read(&monpriv->iucv_severed));
0379         if (ret)
0380             return ret;
0381         if (unlikely(atomic_read(&monpriv->iucv_severed)))
0382             return -EIO;
0383         monmsg = monpriv->msg_array[monpriv->read_index];
0384     }
0385 
0386     if (!monmsg->pos)
0387         monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset;
0388     if (mon_check_mca(monmsg))
0389         goto reply;
0390 
0391     /* read monitor control element (12 bytes) first */
0392     mce_start = mon_mca_start(monmsg) + monmsg->mca_offset;
0393     if ((monmsg->pos >= mce_start) && (monmsg->pos < mce_start + 12)) {
0394         count = min(count, (size_t) mce_start + 12 - monmsg->pos);
0395         ret = copy_to_user(data, (void *) (unsigned long) monmsg->pos,
0396                    count);
0397         if (ret)
0398             return -EFAULT;
0399         monmsg->pos += count;
0400         if (monmsg->pos == mce_start + 12)
0401             monmsg->pos = mon_rec_start(monmsg);
0402         goto out_copy;
0403     }
0404 
0405     /* read records */
0406     if (monmsg->pos <= mon_rec_end(monmsg)) {
0407         count = min(count, (size_t) mon_rec_end(monmsg) - monmsg->pos
0408                         + 1);
0409         ret = copy_to_user(data, (void *) (unsigned long) monmsg->pos,
0410                    count);
0411         if (ret)
0412             return -EFAULT;
0413         monmsg->pos += count;
0414         if (monmsg->pos > mon_rec_end(monmsg))
0415             mon_next_mca(monmsg);
0416         goto out_copy;
0417     }
0418 reply:
0419     ret = mon_send_reply(monmsg, monpriv);
0420     return ret;
0421 
0422 out_copy:
0423     *ppos += count;
0424     return count;
0425 }
0426 
0427 static __poll_t mon_poll(struct file *filp, struct poll_table_struct *p)
0428 {
0429     struct mon_private *monpriv = filp->private_data;
0430 
0431     poll_wait(filp, &mon_read_wait_queue, p);
0432     if (unlikely(atomic_read(&monpriv->iucv_severed)))
0433         return EPOLLERR;
0434     if (atomic_read(&monpriv->read_ready))
0435         return EPOLLIN | EPOLLRDNORM;
0436     return 0;
0437 }
0438 
0439 static const struct file_operations mon_fops = {
0440     .owner   = THIS_MODULE,
0441     .open    = &mon_open,
0442     .release = &mon_close,
0443     .read    = &mon_read,
0444     .poll    = &mon_poll,
0445     .llseek  = noop_llseek,
0446 };
0447 
0448 static struct miscdevice mon_dev = {
0449     .name       = "monreader",
0450     .fops       = &mon_fops,
0451     .minor      = MISC_DYNAMIC_MINOR,
0452 };
0453 
0454 /******************************************************************************
0455  *                              module init/exit                              *
0456  *****************************************************************************/
0457 static int __init mon_init(void)
0458 {
0459     int rc;
0460 
0461     if (!MACHINE_IS_VM) {
0462         pr_err("The z/VM *MONITOR record device driver cannot be "
0463                "loaded without z/VM\n");
0464         return -ENODEV;
0465     }
0466 
0467     /*
0468      * Register with IUCV and connect to *MONITOR service
0469      */
0470     rc = iucv_register(&monreader_iucv_handler, 1);
0471     if (rc) {
0472         pr_err("The z/VM *MONITOR record device driver failed to "
0473                "register with IUCV\n");
0474         return rc;
0475     }
0476 
0477     rc = segment_type(mon_dcss_name);
0478     if (rc < 0) {
0479         segment_warning(rc, mon_dcss_name);
0480         goto out_iucv;
0481     }
0482     if (rc != SEG_TYPE_SC) {
0483         pr_err("The specified *MONITOR DCSS %s does not have the "
0484                "required type SC\n", mon_dcss_name);
0485         rc = -EINVAL;
0486         goto out_iucv;
0487     }
0488 
0489     rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
0490               &mon_dcss_start, &mon_dcss_end);
0491     if (rc < 0) {
0492         segment_warning(rc, mon_dcss_name);
0493         rc = -EINVAL;
0494         goto out_iucv;
0495     }
0496     dcss_mkname(mon_dcss_name, &user_data_connect[8]);
0497 
0498     /*
0499      * misc_register() has to be the last action in module_init(), because
0500      * file operations will be available right after this.
0501      */
0502     rc = misc_register(&mon_dev);
0503     if (rc < 0 )
0504         goto out;
0505     return 0;
0506 
0507 out:
0508     segment_unload(mon_dcss_name);
0509 out_iucv:
0510     iucv_unregister(&monreader_iucv_handler, 1);
0511     return rc;
0512 }
0513 
0514 static void __exit mon_exit(void)
0515 {
0516     segment_unload(mon_dcss_name);
0517     misc_deregister(&mon_dev);
0518     iucv_unregister(&monreader_iucv_handler, 1);
0519     return;
0520 }
0521 
0522 
0523 module_init(mon_init);
0524 module_exit(mon_exit);
0525 
0526 module_param_string(mondcss, mon_dcss_name, 9, 0444);
0527 MODULE_PARM_DESC(mondcss, "Name of DCSS segment to be used for *MONITOR "
0528          "service, max. 8 chars. Default is MONDCSS");
0529 
0530 MODULE_AUTHOR("Gerald Schaefer <geraldsc@de.ibm.com>");
0531 MODULE_DESCRIPTION("Character device driver for reading z/VM "
0532            "monitor service records.");
0533 MODULE_LICENSE("GPL");