+
+/*-----------------------------------------------------------------------
+** vmm_set_XA
+**
+** This function sets the eXtended Architecture flags for the specifed VM.
+**
+** We need to return the result in the return code rather than in the return parameters
+** because we need an architecture independent format so the results are actually
+** usable by the host. For example, the return parameters for 64-bit are 8 bytes wide vs.
+** 4 for 32-bit.
+**
+** Note that this function does a lot of the same stuff as vmm_tear_down_context
+** and vmm_init_context.
+**
+** Inputs:
+** act - pointer to current thread activation structure
+** index - index returned by vmm_init_context
+** flags - the extended architecture flags
+**
+**
+** Outputs:
+** KERN_SUCCESS if vm is valid and initialized. KERN_FAILURE if not.
+** Also, the internal flags are set and, additionally, the VM is completely reset.
+-----------------------------------------------------------------------*/
+
+kern_return_t vmm_set_XA(
+ thread_act_t act,
+ vmm_thread_index_t index,
+ unsigned int xaflags)
+{
+ vmmCntrlEntry *CEntry;
+ vmmCntrlTable *CTable;
+ vmm_state_page_t *vks;
+ vmm_version_t version;
+
+ if(xaflags & ~vmm64Bit) return KERN_FAILURE; /* We only support this one kind now */
+
+ CEntry = vmm_get_entry(act, index); /* Convert index to entry */
+ if (CEntry == NULL) return KERN_FAILURE; /* Either this isn't a vmm or the index is bogus */
+
+ ml_set_interrupts_enabled(TRUE); /* This can take a bit of time so pass interruptions */
+
+ if(CEntry->vmmFacCtx.FPUsave) { /* Is there any floating point context? */
+ toss_live_fpu(&CEntry->vmmFacCtx); /* Get rid of any live context here */
+ save_release((savearea *)CEntry->vmmFacCtx.FPUsave); /* Release it */
+ }
+
+ if(CEntry->vmmFacCtx.VMXsave) { /* Is there any vector context? */
+ toss_live_vec(&CEntry->vmmFacCtx); /* Get rid of any live context here */
+ save_release((savearea *)CEntry->vmmFacCtx.VMXsave); /* Release it */
+ }
+
+ CTable = act->mact.vmmControl; /* Get the control table address */
+ CTable->vmmGFlags = CTable->vmmGFlags & ~vmmLastAdSp; /* Make sure we don't try to automap into this */
+
+ CEntry->vmmFlags &= vmmInUse; /* Clear out all of the flags for this entry except in use */
+ CEntry->vmmXAFlgs = (xaflags & vmm64Bit) | (CEntry->vmmXAFlgs & ~vmm64Bit); /* Set the XA flags */
+ CEntry->vmmFacCtx.FPUsave = 0; /* Clear facility context control */
+ CEntry->vmmFacCtx.FPUlevel = 0; /* Clear facility context control */
+ CEntry->vmmFacCtx.FPUcpu = 0; /* Clear facility context control */
+ CEntry->vmmFacCtx.VMXsave = 0; /* Clear facility context control */
+ CEntry->vmmFacCtx.VMXlevel = 0; /* Clear facility context control */
+ CEntry->vmmFacCtx.VMXcpu = 0; /* Clear facility context control */
+
+ vks = CEntry->vmmContextKern; /* Get address of the context page */
+ version = vks->interface_version; /* Save the version code */
+ bzero((char *)vks, 4096); /* Clear all */
+
+ vks->interface_version = version; /* Set our version code */
+ vks->thread_index = index % vmmTInum; /* Tell the user the index for this virtual machine */
+
+ ml_set_interrupts_enabled(FALSE); /* No more interruptions */
+
+ return KERN_SUCCESS; /* Return the flags */
+}
+
+