return 0;
 }
 
+/**
+ * sgx_encl_ewb_cpumask() - Query which CPUs might be accessing the enclave
+ * @encl: the enclave
+ *
+ * Some SGX functions require that no cached linear-to-physical address
+ * mappings are present before they can succeed. For example, ENCLS[EWB]
+ * copies a page from the enclave page cache to regular main memory but
+ * it fails if it cannot ensure that there are no cached
+ * linear-to-physical address mappings referring to the page.
+ *
+ * SGX hardware flushes all cached linear-to-physical mappings on a CPU
+ * when an enclave is exited via ENCLU[EEXIT] or an Asynchronous Enclave
+ * Exit (AEX). Exiting an enclave will thus ensure cached linear-to-physical
+ * address mappings are cleared but coordination with the tracking done within
+ * the SGX hardware is needed to support the SGX functions that depend on this
+ * cache clearing.
+ *
+ * When the ENCLS[ETRACK] function is issued on an enclave the hardware
+ * tracks threads operating inside the enclave at that time. The SGX
+ * hardware tracking require that all the identified threads must have
+ * exited the enclave in order to flush the mappings before a function such
+ * as ENCLS[EWB] will be permitted
+ *
+ * The following flow is used to support SGX functions that require that
+ * no cached linear-to-physical address mappings are present:
+ * 1) Execute ENCLS[ETRACK] to initiate hardware tracking.
+ * 2) Use this function (sgx_encl_ewb_cpumask()) to query which CPUs might be
+ *    accessing the enclave.
+ * 3) Send IPI to identified CPUs, kicking them out of the enclave and
+ *    thus flushing all locally cached linear-to-physical address mappings.
+ * 4) Execute SGX function.
+ *
+ * Context: It is required to call this function after ENCLS[ETRACK].
+ *          This will ensure that if any new mm appears (racing with
+ *          sgx_encl_mm_add()) then the new mm will enter into the
+ *          enclave with fresh linear-to-physical address mappings.
+ *
+ *          It is required that all IPIs are completed before a new
+ *          ENCLS[ETRACK] is issued so be sure to protect steps 1 to 3
+ *          of the above flow with the enclave's mutex.
+ *
+ * Return: cpumask of CPUs that might be accessing @encl
+ */
+const cpumask_t *sgx_encl_ewb_cpumask(struct sgx_encl *encl)
+{
+       cpumask_t *cpumask = &encl->cpumask;
+       struct sgx_encl_mm *encl_mm;
+       int idx;
+
+       cpumask_clear(cpumask);
+
+       idx = srcu_read_lock(&encl->srcu);
+
+       list_for_each_entry_rcu(encl_mm, &encl->mm_list, list) {
+               if (!mmget_not_zero(encl_mm->mm))
+                       continue;
+
+               cpumask_or(cpumask, cpumask, mm_cpumask(encl_mm->mm));
+
+               mmput_async(encl_mm->mm);
+       }
+
+       srcu_read_unlock(&encl->srcu, idx);
+
+       return cpumask;
+}
+
 static struct page *sgx_encl_get_backing_page(struct sgx_encl *encl,
                                              pgoff_t index)
 {
 
 {
 }
 
-static const cpumask_t *sgx_encl_ewb_cpumask(struct sgx_encl *encl)
-{
-       cpumask_t *cpumask = &encl->cpumask;
-       struct sgx_encl_mm *encl_mm;
-       int idx;
-
-       /*
-        * Can race with sgx_encl_mm_add(), but ETRACK has already been
-        * executed, which means that the CPUs running in the new mm will enter
-        * into the enclave with a fresh epoch.
-        */
-       cpumask_clear(cpumask);
-
-       idx = srcu_read_lock(&encl->srcu);
-
-       list_for_each_entry_rcu(encl_mm, &encl->mm_list, list) {
-               if (!mmget_not_zero(encl_mm->mm))
-                       continue;
-
-               cpumask_or(cpumask, cpumask, mm_cpumask(encl_mm->mm));
-
-               mmput_async(encl_mm->mm);
-       }
-
-       srcu_read_unlock(&encl->srcu, idx);
-
-       return cpumask;
-}
-
 /*
  * Swap page to the regular memory transformed to the blocked state by using
  * EBLOCK, which means that it can no longer be referenced (no new TLB entries).