Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 31 Jan 2020 19:05:33 +0000 (11:05 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 31 Jan 2020 19:05:33 +0000 (11:05 -0800)
Pull x86 fixes from Ingo Molnar:
 "Misc fixes:

   - three fixes and a cleanup for the resctrl code

   - a HyperV fix

   - a fix to /proc/kcore contents in live debugging sessions

   - a fix for the x86 decoder opcode map"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/decoder: Add TEST opcode to Group3-2
  x86/resctrl: Clean up unused function parameter in mkdir path
  x86/resctrl: Fix a deadlock due to inaccurate reference
  x86/resctrl: Fix use-after-free due to inaccurate refcount of rdtgroup
  x86/resctrl: Fix use-after-free when deleting resource groups
  x86/hyper-v: Add "polling" bit to hv_synic_sint
  x86/crash: Define arch_crash_save_vmcoreinfo() if CONFIG_CRASH_CORE=y

1  2 
arch/x86/kernel/cpu/resctrl/rdtgroup.c

@@@ -532,15 -532,11 +532,15 @@@ static void move_myself(struct callback
                kfree(rdtgrp);
        }
  
 +      if (unlikely(current->flags & PF_EXITING))
 +              goto out;
 +
        preempt_disable();
        /* update PQR_ASSOC MSR to make resource group go into effect */
        resctrl_sched_in();
        preempt_enable();
  
 +out:
        kfree(callback);
  }
  
@@@ -729,92 -725,6 +729,92 @@@ static int rdtgroup_tasks_show(struct k
        return ret;
  }
  
 +#ifdef CONFIG_PROC_CPU_RESCTRL
 +
 +/*
 + * A task can only be part of one resctrl control group and of one monitor
 + * group which is associated to that control group.
 + *
 + * 1)   res:
 + *      mon:
 + *
 + *    resctrl is not available.
 + *
 + * 2)   res:/
 + *      mon:
 + *
 + *    Task is part of the root resctrl control group, and it is not associated
 + *    to any monitor group.
 + *
 + * 3)  res:/
 + *     mon:mon0
 + *
 + *    Task is part of the root resctrl control group and monitor group mon0.
 + *
 + * 4)  res:group0
 + *     mon:
 + *
 + *    Task is part of resctrl control group group0, and it is not associated
 + *    to any monitor group.
 + *
 + * 5) res:group0
 + *    mon:mon1
 + *
 + *    Task is part of resctrl control group group0 and monitor group mon1.
 + */
 +int proc_resctrl_show(struct seq_file *s, struct pid_namespace *ns,
 +                    struct pid *pid, struct task_struct *tsk)
 +{
 +      struct rdtgroup *rdtg;
 +      int ret = 0;
 +
 +      mutex_lock(&rdtgroup_mutex);
 +
 +      /* Return empty if resctrl has not been mounted. */
 +      if (!static_branch_unlikely(&rdt_enable_key)) {
 +              seq_puts(s, "res:\nmon:\n");
 +              goto unlock;
 +      }
 +
 +      list_for_each_entry(rdtg, &rdt_all_groups, rdtgroup_list) {
 +              struct rdtgroup *crg;
 +
 +              /*
 +               * Task information is only relevant for shareable
 +               * and exclusive groups.
 +               */
 +              if (rdtg->mode != RDT_MODE_SHAREABLE &&
 +                  rdtg->mode != RDT_MODE_EXCLUSIVE)
 +                      continue;
 +
 +              if (rdtg->closid != tsk->closid)
 +                      continue;
 +
 +              seq_printf(s, "res:%s%s\n", (rdtg == &rdtgroup_default) ? "/" : "",
 +                         rdtg->kn->name);
 +              seq_puts(s, "mon:");
 +              list_for_each_entry(crg, &rdtg->mon.crdtgrp_list,
 +                                  mon.crdtgrp_list) {
 +                      if (tsk->rmid != crg->mon.rmid)
 +                              continue;
 +                      seq_printf(s, "%s", crg->kn->name);
 +                      break;
 +              }
 +              seq_putc(s, '\n');
 +              goto unlock;
 +      }
 +      /*
 +       * The above search should succeed. Otherwise return
 +       * with an error.
 +       */
 +      ret = -ENOENT;
 +unlock:
 +      mutex_unlock(&rdtgroup_mutex);
 +
 +      return ret;
 +}
 +#endif
 +
  static int rdt_last_cmd_status_show(struct kernfs_open_file *of,
                                    struct seq_file *seq, void *v)
  {
@@@ -2060,7 -1970,7 +2060,7 @@@ static int rdt_get_tree(struct fs_conte
  
        if (rdt_mon_capable) {
                ret = mongroup_create_dir(rdtgroup_default.kn,
-                                         NULL, "mon_groups",
+                                         &rdtgroup_default, "mon_groups",
                                          &kn_mongrp);
                if (ret < 0)
                        goto out_info;
@@@ -2295,7 -2205,11 +2295,11 @@@ static void free_all_child_rdtgrp(struc
        list_for_each_entry_safe(sentry, stmp, head, mon.crdtgrp_list) {
                free_rmid(sentry->mon.rmid);
                list_del(&sentry->mon.crdtgrp_list);
-               kfree(sentry);
+               if (atomic_read(&sentry->waitcount) != 0)
+                       sentry->flags = RDT_DELETED;
+               else
+                       kfree(sentry);
        }
  }
  
@@@ -2333,7 -2247,11 +2337,11 @@@ static void rmdir_all_sub(void
  
                kernfs_remove(rdtgrp->kn);
                list_del(&rdtgrp->rdtgroup_list);
-               kfree(rdtgrp);
+               if (atomic_read(&rdtgrp->waitcount) != 0)
+                       rdtgrp->flags = RDT_DELETED;
+               else
+                       kfree(rdtgrp);
        }
        /* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */
        update_closid_rmid(cpu_online_mask, &rdtgroup_default);
@@@ -2536,7 -2454,7 +2544,7 @@@ static int mkdir_mondata_all(struct ker
        /*
         * Create the mon_data directory first.
         */
-       ret = mongroup_create_dir(parent_kn, NULL, "mon_data", &kn);
+       ret = mongroup_create_dir(parent_kn, prgrp, "mon_data", &kn);
        if (ret)
                return ret;
  
@@@ -2726,7 -2644,6 +2734,6 @@@ static int rdtgroup_init_alloc(struct r
  }
  
  static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
-                            struct kernfs_node *prgrp_kn,
                             const char *name, umode_t mode,
                             enum rdt_group_type rtype, struct rdtgroup **r)
  {
        uint files = 0;
        int ret;
  
-       prdtgrp = rdtgroup_kn_lock_live(prgrp_kn);
+       prdtgrp = rdtgroup_kn_lock_live(parent_kn);
        if (!prdtgrp) {
                ret = -ENODEV;
                goto out_unlock;
        kernfs_activate(kn);
  
        /*
-        * The caller unlocks the prgrp_kn upon success.
+        * The caller unlocks the parent_kn upon success.
         */
        return 0;
  
@@@ -2819,7 -2736,7 +2826,7 @@@ out_destroy
  out_free_rgrp:
        kfree(rdtgrp);
  out_unlock:
-       rdtgroup_kn_unlock(prgrp_kn);
+       rdtgroup_kn_unlock(parent_kn);
        return ret;
  }
  
@@@ -2836,15 -2753,12 +2843,12 @@@ static void mkdir_rdt_prepare_clean(str
   * to monitor a subset of tasks and cpus in its parent ctrl_mon group.
   */
  static int rdtgroup_mkdir_mon(struct kernfs_node *parent_kn,
-                             struct kernfs_node *prgrp_kn,
-                             const char *name,
-                             umode_t mode)
+                             const char *name, umode_t mode)
  {
        struct rdtgroup *rdtgrp, *prgrp;
        int ret;
  
-       ret = mkdir_rdt_prepare(parent_kn, prgrp_kn, name, mode, RDTMON_GROUP,
-                               &rdtgrp);
+       ret = mkdir_rdt_prepare(parent_kn, name, mode, RDTMON_GROUP, &rdtgrp);
        if (ret)
                return ret;
  
         */
        list_add_tail(&rdtgrp->mon.crdtgrp_list, &prgrp->mon.crdtgrp_list);
  
-       rdtgroup_kn_unlock(prgrp_kn);
+       rdtgroup_kn_unlock(parent_kn);
        return ret;
  }
  
   * to allocate and monitor resources.
   */
  static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn,
-                                  struct kernfs_node *prgrp_kn,
                                   const char *name, umode_t mode)
  {
        struct rdtgroup *rdtgrp;
        u32 closid;
        int ret;
  
-       ret = mkdir_rdt_prepare(parent_kn, prgrp_kn, name, mode, RDTCTRL_GROUP,
-                               &rdtgrp);
+       ret = mkdir_rdt_prepare(parent_kn, name, mode, RDTCTRL_GROUP, &rdtgrp);
        if (ret)
                return ret;
  
                 * Create an empty mon_groups directory to hold the subset
                 * of tasks and cpus to monitor.
                 */
-               ret = mongroup_create_dir(kn, NULL, "mon_groups", NULL);
+               ret = mongroup_create_dir(kn, rdtgrp, "mon_groups", NULL);
                if (ret) {
                        rdt_last_cmd_puts("kernfs subdir error\n");
                        goto out_del_list;
@@@ -2916,7 -2828,7 +2918,7 @@@ out_id_free
  out_common_fail:
        mkdir_rdt_prepare_clean(rdtgrp);
  out_unlock:
-       rdtgroup_kn_unlock(prgrp_kn);
+       rdtgroup_kn_unlock(parent_kn);
        return ret;
  }
  
@@@ -2949,14 -2861,14 +2951,14 @@@ static int rdtgroup_mkdir(struct kernfs
         * subdirectory
         */
        if (rdt_alloc_capable && parent_kn == rdtgroup_default.kn)
-               return rdtgroup_mkdir_ctrl_mon(parent_kn, parent_kn, name, mode);
+               return rdtgroup_mkdir_ctrl_mon(parent_kn, name, mode);
  
        /*
         * If RDT monitoring is supported and the parent directory is a valid
         * "mon_groups" directory, add a monitoring subdirectory.
         */
        if (rdt_mon_capable && is_mon_groups(parent_kn, name))
-               return rdtgroup_mkdir_mon(parent_kn, parent_kn->parent, name, mode);
+               return rdtgroup_mkdir_mon(parent_kn, name, mode);
  
        return -EPERM;
  }
@@@ -3042,13 -2954,13 +3044,13 @@@ static int rdtgroup_rmdir_ctrl(struct k
        closid_free(rdtgrp->closid);
        free_rmid(rdtgrp->mon.rmid);
  
+       rdtgroup_ctrl_remove(kn, rdtgrp);
        /*
         * Free all the child monitor group rmids.
         */
        free_all_child_rdtgrp(rdtgrp);
  
-       rdtgroup_ctrl_remove(kn, rdtgrp);
        return 0;
  }