Note first, the following will use trap as a collective term for faults, aborts and traps.
External interrupts will be forwarded to the host context by the quickest possible route where they will be reasserted. The other events will be categorized into virtualization traps, genuine guest traps and hypervisor traps. The latter group may be recoverable depending on when they happen and whether there is a handler for it, otherwise it will cause a guru meditation.
TRPM disgishishes the between the first two (virt and guest traps) and the latter (hyper) by checking the CPL of the trapping code, if CPL == 0 then it's a hyper trap otherwise it's a virt/guest trap. There are three trap dispatcher tables, one ad-hoc for one time traps registered via TRPMGCSetTempHandler(), one for hyper traps and one for virt/guest traps. The latter two live in TRPMGCHandlersA.asm, the former in the VM structure.
The raw-mode context trap handlers found in TRPMGCHandlers.cpp (for the most part), will call up the other VMM sub-systems depending on what it things happens. The two most busy traps are page faults (#PF) and general protection fault/trap (#GP).
Before resuming guest code after having taken a virtualization trap or injected a guest trap, TRPM will check for pending forced action and every now and again let TM check for timed out timers. This allows code that is being executed as part of virtualization traps to signal ring-3 exits, page table resyncs and similar without necessarily using the status code. It also make sure we're more responsive to timers and requests from other threads (necessarily running on some different core/cpu in most cases).TRPM will also dispatch / inject interrupts and traps to the guest, both when in raw-mode and when in hardware assisted mode. See TRPMInject().