mirror of
				https://gitlab.com/qemu-project/edk2.git
				synced 2025-10-30 07:56:39 +08:00 
			
		
		
		
	 34cd1aca46
			
		
	
	34cd1aca46
	
	
	
		
			
			TR is used to enable a separate safe stack when a stack overflow occurs. When PEI starts up the APs, TR is non-zero and so each processor has its own GDT. TR is an offset into the GDT and so points to a different TSS entry in each AP. There is a small window in early DXE after MpInitLibInitialize() is called where: - TR is non-zero because it has been inherited from the PEI phase - TR is not restored to 0 - The APs are all switched to using the BSP's GDT - SaveVolatileRegisters() is called from ApWakeupFunction() before the APs go to sleep, which saves the non-zero TR value to CpuMpData->CpuData[].VolatileRegisters.Tr, cause TR to point to the same TSS entry in the BSP's GDT - The next time the APs are woken up, RestoreVolatileRegisters() is called from ApWakeupFunction() which would attempt to load the non-zero TR value into the actual task register, which creates a race condition to a #GP fault because loading the task register sets the busy bit in the TSS descriptor and a #GP fault occurs if the busy bit is already set when loading the task register. To avoid this issue, the task register is only loaded if TR is non-zero and the TSS descriptor is valid and not busy. HW sets the busy bit and does not clear it. edk2 does not clear the busy bit, so the BSP's TSS descriptor will be marked busy forever and the APs will not load the task register until they have their own GDT/TSS set up. Co-authored-by: Ray Ni <ray.ni@intel.com> Signed-off-by: Oliver Smith-Denny <osde@microsoft.com>