* separate MCEs from kernel messages to avoid bogus bug reports.
  */
 
-static struct mce_log_buffer mcelog = {
-       .signature      = MCE_LOG_SIGNATURE,
-       .len            = MCE_LOG_LEN,
-       .recordlen      = sizeof(struct mce),
-};
+static struct mce_log_buffer *mcelog;
 
 static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait);
 
 
        mutex_lock(&mce_chrdev_read_mutex);
 
-       entry = mcelog.next;
+       entry = mcelog->next;
 
        /*
         * When the buffer fills up discard new entries. Assume that the
         * earlier errors are the more interesting ones:
         */
-       if (entry >= MCE_LOG_LEN) {
-               set_bit(MCE_OVERFLOW, (unsigned long *)&mcelog.flags);
+       if (entry >= mcelog->len) {
+               set_bit(MCE_OVERFLOW, (unsigned long *)&mcelog->flags);
                goto unlock;
        }
 
-       mcelog.next = entry + 1;
+       mcelog->next = entry + 1;
 
-       memcpy(mcelog.entry + entry, mce, sizeof(struct mce));
-       mcelog.entry[entry].finished = 1;
+       memcpy(mcelog->entry + entry, mce, sizeof(struct mce));
+       mcelog->entry[entry].finished = 1;
 
        /* wake processes polling /dev/mcelog */
        wake_up_interruptible(&mce_chrdev_wait);
 
        /* Only supports full reads right now */
        err = -EINVAL;
-       if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce))
+       if (*off != 0 || usize < mcelog->len * sizeof(struct mce))
                goto out;
 
-       next = mcelog.next;
+       next = mcelog->next;
        err = 0;
 
        for (i = 0; i < next; i++) {
-               struct mce *m = &mcelog.entry[i];
+               struct mce *m = &mcelog->entry[i];
 
                err |= copy_to_user(buf, m, sizeof(*m));
                buf += sizeof(*m);
        }
 
-       memset(mcelog.entry, 0, next * sizeof(struct mce));
-       mcelog.next = 0;
+       memset(mcelog->entry, 0, next * sizeof(struct mce));
+       mcelog->next = 0;
 
        if (err)
                err = -EFAULT;
 static __poll_t mce_chrdev_poll(struct file *file, poll_table *wait)
 {
        poll_wait(file, &mce_chrdev_wait, wait);
-       if (READ_ONCE(mcelog.next))
+       if (READ_ONCE(mcelog->next))
                return EPOLLIN | EPOLLRDNORM;
        if (!mce_apei_read_done && apei_check_mce())
                return EPOLLIN | EPOLLRDNORM;
        case MCE_GET_RECORD_LEN:
                return put_user(sizeof(struct mce), p);
        case MCE_GET_LOG_LEN:
-               return put_user(MCE_LOG_LEN, p);
+               return put_user(mcelog->len, p);
        case MCE_GETCLEAR_FLAGS: {
                unsigned flags;
 
                do {
-                       flags = mcelog.flags;
-               } while (cmpxchg(&mcelog.flags, flags, 0) != flags);
+                       flags = mcelog->flags;
+               } while (cmpxchg(&mcelog->flags, flags, 0) != flags);
 
                return put_user(flags, p);
        }
 
 static __init int dev_mcelog_init_device(void)
 {
+       int mce_log_len;
        int err;
 
+       mce_log_len = max(MCE_LOG_MIN_LEN, num_online_cpus());
+       mcelog = kzalloc(sizeof(*mcelog) + mce_log_len * sizeof(struct mce), GFP_KERNEL);
+       if (!mcelog)
+               return -ENOMEM;
+
+       strncpy(mcelog->signature, MCE_LOG_SIGNATURE, sizeof(mcelog->signature));
+       mcelog->len = mce_log_len;
+       mcelog->recordlen = sizeof(struct mce);
+
        /* register character device /dev/mcelog */
        err = misc_register(&mce_chrdev_device);
        if (err) {
                else
                        pr_err("Unable to init device /dev/mcelog (rc: %d)\n", err);
 
+               kfree(mcelog);
                return err;
        }