コード例 #1
0
ファイル: kernelswi.c プロジェクト: jonmcdonald/VistaModels
//---------------------------------------------------------------------------
void PendSV_Handler(void)
{

	//-----------------------------------------------------------------------
	// Context switch from Pend ISR 
	//-----------------------------------------------------------------------
	Task_SaveContext();
	Task_Switch();
	Task_RestoreContext();
}
コード例 #2
0
int
Vmx86_RunVM(VMDriver *vm,   // IN:
            Vcpuid vcpuid)  // IN:
{
   uint32 retval = MODULECALL_USERRETURN;
   VMCrossPage *crosspage = vm->crosspage[vcpuid];
   int bailValue = 0;

   ASSERT(crosspage);

   /*
    * Check if we were interrupted by signal.
    */
   if (crosspage->moduleCallInterrupted) {
      crosspage->moduleCallInterrupted = FALSE;
      goto skipTaskSwitch;
   }

   for (;;) {
      /*
       * Task_Switch changes the world to the monitor.
       * The monitor is waiting in the BackToHost routine.
       */
      UCTIMESTAMP(crosspage, SWITCHING_TO_MONITOR);
      Task_Switch(vm, vcpuid);
      UCTIMESTAMP(crosspage, SWITCHED_TO_MODULE);
      if (crosspage->yieldVCPU &&
          (crosspage->moduleCallType != MODULECALL_YIELD)) {
         HostIF_YieldCPU(0);
      }


skipTaskSwitch:;

      retval = MODULECALL_USERRETURN;

      if (crosspage->userCallType != MODULECALL_USERCALL_NONE) {
         /*
          * This is the main user call path.
          *
          * There are two kinds of user calls.  Normal ones are handled by the
          * calling VCPU thread itself.  We just return from here (back to
          * userlevel) in that case.
          *
          * Calls marked userCallCross are handled by the main VMX thread.  In
          * this case, the userCallRequest field indicates to the VMX that
          * this VCPU wants to make a user call.  This field may be consulted
          * by the VMX at any time (specifically when the VMX is awakened by
          * another VCPU), so it must be set after the other user call
          * arguments.  The VMX is responsible for resetting this field and
          * awakening the VCPU when the user call is complete, via the
          * ACK_USER_CALL and COMPLETE_USER_CALL ioctl.  The latter implies
          * the former.
          *
          * When and how to use ACK_USER_CALL and COMPLETE_USER_CALL are at
          * the discretion of the VMX.  In particular, COMPLETE_USER_CALL
          * does not imply that the requested operation has fully completed,
          * only that the VCPU can continue.  See the comment in
          * MonitorLoopCrossUserCallPoll() for use scenarios.
          *
          * -- edward
          */

         if (!crosspage->userCallCross) {
            ASSERT(!crosspage->userCallRestart);
            bailValue = crosspage->userCallType;
            crosspage->retval = retval;
            goto bailOut;
         }

         if (!crosspage->userCallRestart) {
            ASSERT(crosspage->userCallRequest == MODULECALL_USERCALL_NONE);
            crosspage->userCallRequest = crosspage->userCallType;
            UCTIMESTAMP(crosspage, AWAKENING_VMX);
            HostIF_UserCall(vm, vcpuid);
         }

         UCTIMESTAMP(crosspage, GOING_TO_SLEEP);
         if (HostIF_UserCallWait(vm, vcpuid, USERCALL_TIMEOUT)) {
            ASSERT(crosspage->userCallRequest == MODULECALL_USERCALL_NONE);
         } else {
            retval = MODULECALL_USERTIMEOUT;
         }
         UCTIMESTAMP(crosspage, AWAKE);
      }

      switch (crosspage->moduleCallType) {
      case MODULECALL_NONE:
         break;

      case MODULECALL_INTR:    // Already done in task.c
         break;

      case MODULECALL_GET_RECYCLED_PAGE: {
         MPN32 mpn;
    
         retval = (Vmx86_AllocLockedPages(vm, PtrToVA64(&mpn), 1, TRUE) == 1) ?
                   mpn : INVALID_MPN;
         break;
      }

      case MODULECALL_SEMAWAIT: {
         retval = HostIF_SemaphoreWait(vm, vcpuid, crosspage->args);

         if (retval == MX_WAITINTERRUPTED) {
            crosspage->moduleCallInterrupted = TRUE;
            bailValue = USERCALL_RESTART;
            goto bailOut;
         }
         break;
      }

      case MODULECALL_SEMASIGNAL: {
         retval = HostIF_SemaphoreSignal(crosspage->args);

         if (retval == MX_WAITINTERRUPTED) {
             crosspage->moduleCallInterrupted = TRUE;
             bailValue = USERCALL_RESTART;
             goto bailOut;
         }
         break;
      }

      case MODULECALL_SEMAFORCEWAKEUP: {
         HostIF_SemaphoreForceWakeup(vm, (Vcpuid) crosspage->args[0]);
         break;
      }

      case MODULECALL_IPI: {
         Bool didBroadcast;
         retval = HostIF_IPI(vm, (VCPUSet)(uintptr_t)crosspage->args[0], 
                             TRUE, &didBroadcast);
         break;
      }

      case MODULECALL_RELEASE_ANON_PAGES: {
         unsigned count = 1;
         MPN32 mpns[3];
         mpns[0] = (MPN32)crosspage->args[0];
         mpns[1] = (MPN32)crosspage->args[1];
         mpns[2] = (MPN32)crosspage->args[2];
         if (mpns[1] != INVALID_MPN) {
            count++;
            if (mpns[2] != INVALID_MPN) {
               count++;
            }
         }
         retval = Vmx86_FreeLockedPages(vm, PtrToVA64(mpns), count, TRUE);
         break;
      }

      case MODULECALL_IS_ANON_PAGE: {
         MPN32 mpn = (MPN32)crosspage->args[0];
         retval = Vmx86_IsAnonPage(vm, mpn);
         break;
      }

      case MODULECALL_SWITCH_TO_PEER: {
         crosspage->runVmm64 = !crosspage->runVmm64;
         break;
      }

      case MODULECALL_YIELD: {
         HostIF_YieldCPU(0);
         break;
      }

      case MODULECALL_START_VMX_OP: {
         int numVMCSes;
         int i;

         numVMCSes = crosspage->args[0];
         ASSERT(numVMCSes >= 0);
         ASSERT(numVMCSes <= MAX_DUMMY_VMCSES);
         for (i = 0; i < numVMCSes; i++) {
            MPN dummyVMCS = Task_GetDummyVMCS(i);

            if (dummyVMCS == INVALID_MPN) {
               bailValue = USERCALL_VMX86ALLOCERR;
               goto bailOut;
            }
            crosspage->dummyVMCS[i] = MPN_2_MA(dummyVMCS);
         }

         crosspage->inVMXOperation = 1;
         /*
          * PR 454299: Preserve previous crosspage->retval.
          */
         retval = crosspage->retval;
      } break;

      case MODULECALL_ALLOC_VMX_PAGE: {
         if (Task_GetRootVMCS(crosspage->args[0]) == INVALID_MPN) {
            crosspage->inVMXOperation = 0;

            bailValue = USERCALL_VMX86ALLOCERR;
            goto bailOut;
         }

         retval = crosspage->retval;
      } break;

      default:
         Warning("ModuleCall %d not supported\n", crosspage->moduleCallType);
      }

      crosspage->retval = retval;

#if defined(linux)
      cond_resched(); // Other kernels are preemptable
#endif
   }

bailOut:
   return bailValue;
}