рд▓рд┐рдирдХреНрд╕ рдореЗрдВ x86 рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХрд╛ рд╡рд┐рдХрд╛рд╕



рдкрд┐рдЫрд▓реЗ рд╕рдкреНрддрд╛рд╣рд╛рдВрдд рдореЗрдВ, 80386 рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдк рддрдереНрдпреЛрдВ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рддреЗ рд╣реБрдП, рдореБрдЭреЗ рдЕрдЪрд╛рдирдХ рдпрд╛рдж рдЖрдпрд╛ рдХрд┐ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдХреЗ рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдереЗред рдФрд░ рдореИрдВ рдЙрд╕ рдХреЛрдб рдореЗрдВ рдбреВрдм рдЧрдпрд╛ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдХрдИ рд╕рд╛рд▓реЛрдВ рд╕реЗ рдирд╣реАрдВ рджреЗрдЦрд╛ рдерд╛ред рдЕрдм рдореИрдВрдиреЗ рд▓рд┐рдирдХреНрд╕ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕ рдЕрджреНрднреБрдд рдпрд╛рддреНрд░рд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред рдореИрдВ рд╕рднреА рд╕реЛрдиреЗ рдХреА рдбрд▓реА рдФрд░ рдордЬреЗрджрд╛рд░ рдХрд▓рд╛рдХреГрддрд┐рдпреЛрдВ рдХреЛ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдЬреЛ рдореБрдЭреЗ рд░рд╛рд╕реНрддреЗ рдореЗрдВ рдорд┐рд▓реАрдВред

рдЙрджреНрджреЗрд╢реНрдп: рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЛ рдкрд╣рд▓реЗ (0.01) рд╕реЗ рдмрджрд▓рдХрд░ LTS (4.14.67) рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХреИрд╕реЗ рдЯреНрд░реИрдХ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдкрд╣рд▓реЗ рдФрд░ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдкрд░ рд╡рд┐рд╢реЗрд╖ рдЬреЛрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред


рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдХрд╣рд╛рдиреА рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рд╕рдВрджрд░реНрднреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХ рдЫреЛрдЯреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЖрдзреБрдирд┐рдХ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рд▓рд┐рдирдХреНрд╕ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИред рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдмрд╕ рдЗрд╕ рдХрд╣рд╛рдиреА рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред

рд╣рдо рдХрд┐рд╕ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ?


рдпрджреНрдпрдкрд┐ рдХрдИ рдЪреАрдЬреЗрдВ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд░реНрдиреЗрд▓ рдореЛрдб рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдирд╛, рдПрдХ рдмрд╛рдзрд╛ рд╣реИрдВрдбрд▓рд░ рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдирд╛), рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдЖрдорддреМрд░ рдкрд░ рд╕реНрд╡реАрдХреГрдд рдЕрд░реНрде: рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рдмреАрдЪ рд╕реНрд╡рд┐рдЪ рдХрд░рдирд╛ ред рд▓рд┐рдирдХреНрд╕ рдкрд░, рдпрд╣ switch_to() рдореИрдХреНрд░реЛ рдФрд░ рдЗрд╕рдореЗрдВ рд╕рдм рдХреБрдЫ рд╣реИред

рдпрд╣ рдореИрдХреНрд░реЛ рджреЛ рдФрд░ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рд╕рд░рд▓ рдпрд╛рдВрддреНрд░рд┐рдХ рдХреНрд░рд┐рдпрд╛ рд╣реИ: рдПрдХ рдХрд╛рд░реНрдп рдЕрдиреБрд╕реВрдЪрдХ рдФрд░ рдПрдХ рд╕реАрдкреАрдпреВред рдУрдПрд╕ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдореЗрдВ рдХрд╛рд░реНрдп рдпреЛрдЬрдирд╛ рд░рдгрдиреАрддрд┐рдпреЛрдВ рдХреЛ рдорд┐рд▓рд╛рдиреЗ рдФрд░ рд╕рдордиреНрд╡рдп рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реЛрддреА рд╣реИред рд╕реАрдкреАрдпреВ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рднреА рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЦреБрд▓реЗ рд╣реИрдВ: рд▓рд┐рдирдХреНрд╕ рджрд░реНрдЬрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдЙрдирдХреЗ рдмреАрдЪ рдХрд╛ рдЧрд┐рдпрд░ рд╣реИред рдЗрд╕рдХрд╛ "рдбрд┐рдЬрд╝рд╛рдЗрди" рдЗрд╕рдХреЗ рдкрдбрд╝реЛрд╕рд┐рдпреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдУрдПрд╕ рдХрд╛ рдХрдо рд╕реЗ рдХрдо рджрд┐рд▓рдЪрд╕реНрдк рд╣рд┐рд╕реНрд╕рд╛ рд╣реЛрдиреЗ рдХрд╛ рджрд╛рд╡рд╛ рдХрд░рддрд╛ рд╣реИред рдореИрдВ рджреЛрд╣рд░рд╛рддрд╛ рд╣реВрдВ: рд╡рд╣ рд╡рд╣реА рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред

рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдПрдХ рдЫреЛрдЯреА рд╕реВрдЪреА:

  1. рдХрд╛рд░реНрдпрдХреНрд╖реЗрддреНрд░ рдУрд╡рд░рд░рд╛рдЗрдб: рд╕реНрдЯреИрдХ рд░рд┐рдХрд╡рд░реА (рдПрд╕рдПрд╕: рдПрд╕рдкреА)ред
  2. рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рд░реНрджреЗрд╢ рдЦреЛрдЬреЗрдВ: IP рд░рд┐рдХрд╡рд░реА (CS: IP)ред
  3. рдЯрд╛рд╕реНрдХ рд╕реНрдЯреЗрдЯ рд░рд┐рдХрд╡рд░реА: рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдпреЛрдЬрди рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреА рдмрд╣рд╛рд▓реАред
  4. рдореЗрдореЛрд░реА рдПрдбреНрд░реЗрд╕ рд╕реНрдкреЗрд╕ рд╕реНрд╡реИрдк рдХрд░рдирд╛: рдкреЗрдЬ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА (CR3) рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛
  5. ... рдФрд░ рдмрд╣реБрдд рдХреБрдЫ: рдПрдлрдкреАрдпреВ, рдУрдПрд╕ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВ, рдбрд┐рдмрдЧ рд░рдЬрд┐рд╕реНрдЯрд░, рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб, рдЖрджрд┐ред

рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрдм рдФрд░ рдХрд╣рд╛рдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрджрд┐ рд╕реАрдкреАрдпреВ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд▓реЗрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд▓рд┐рдирдХреНрд╕ 2.2 рд╕реЗ рдкрд╣рд▓реЗ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХрд╛рд░реНрдп 2, 3 рдХреЛ рдЫреБрдкрд╛рддрд╛ рд╣реИ, рдФрд░ 4. рдХрд░реНрдиреЗрд▓ рдореЛрдб рдХреЗ рдмреАрдЪ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╕реЗ рдЯрд╛рд╕реНрдХ 3 рд╕реАрдорд┐рдд рд╣реИред рд╢реЗрдбреНрдпреВрд▓рд░ рд░рд┐рдЯрд░реНрди рдХреЗ рдмрд╛рдж рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдереНрд░реЗрдб рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рдПрдХ iret рдХрд╛рд░реНрдп рд╣реИред рд╡рд┐рднрд┐рдиреНрди рдХрд░реНрдиреЗрд▓ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рдЗрдирдореЗрдВ рд╕реЗ рдХрдИ рдХрд╛рд░реНрдп switch_to() рдФрд░ рдЕрдиреБрд╕реВрдЪрдХ рдХреЗ рдмреАрдЪ switch_to() ред рд╣рдо рдХреЗрд╡рд▓ рдЧрд╛рд░рдВрдЯреА рджреЗ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рд╣рдо рд╣рдореЗрд╢рд╛ рдПрдХ рд╕реНрдЯреИрдХ рд╕реНрд╡реИрдк рдФрд░ рдПрдлрдкреАрдпреВ рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рджреЗрдЦреЗрдВрдЧреЗред

рдпрд╣ рдХрд┐рд╕рдХреЗ рд▓рд┐рдП рд╣реИ?


рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдирд╣реАрдВред рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХреЗрд╡рд▓ x86 рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЛ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдФрд░, рд╕рдВрднрд╡рддрдГ, OS рдбрд┐рдЬрд╝рд╛рдЗрди рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдиреНрдпреВрдирддрдо рд╢рд┐рдХреНрд╖рд╛ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред

рдореБрдЭреЗ рддреБрд░рдВрдд рдпрд╣ рдХрд╣рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдореИрдВ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдХрд╛ рдЕрдиреБрд░рдХреНрд╖рдХ рдпрд╛ рдпреЛрдЧрджрд╛рдирдХрд░реНрддрд╛ рдирд╣реАрдВ рд╣реВрдВред рдЗрди рдХрд╛рдорд░реЗрдбреЛрдВ рд╕реЗ рдпрд╛ рдХрд░реНрдиреЗрд▓ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдореЗрд▓рд┐рдВрдЧ рд╕реВрдЪреА рд╕реЗ рдХреЛрдИ рднреА рдЬрд╛рдирдХрд╛рд░реА рдЬреЛ рдореЗрд░реА рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╡рд┐рдкрд░реАрдд рд╣реИ, рдХреЛ рдЧрдВрднреАрд░рддрд╛ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИ, рди рдХрд┐ рдПрдХ рд╕рд╣рдХрд░реНрдореА рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХреА рдЧрдИ рдкрддреНрд░рд┐рдХрд╛ рдореЗрдВ рдПрдХ рд╡реИрдЬреНрдЮрд╛рдирд┐рдХ рд▓реЗрдЦред

1.0 рд╕реЗ рдкрд╣рд▓реЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд▓рд┐рдирдХреНрд╕: рдкреНрд░рд╛рдЪреАрди рдЗрддрд┐рд╣рд╛рд╕ (1991)


рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рд╕рд░рд▓ рдФрд░ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рдореБрдЦ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреА рдПрдХ рдЫреЛрдЯреА рд╕реВрдЪреА рд╣реИ:

  • рдПрдХрд▓ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ (80386 / i386): рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪред рдХрдИ 80386 рд╕реБрд╡рд┐рдзрд╛рдПрдБ рдкреВрд░реЗ рдХреЛрд░ рдореЗрдВ рд╣рд╛рд░реНрдбрдХреЛрдб рдХреА рдЧрдИ рд╣реИрдВред рдЗрди рднрд╛рдЧреЛрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЗрдВрдЯреЗрд▓ 80386 рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдЧрд╛рдЗрдб (1986) рд▓рд┐рдпрд╛ред
  • рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ: рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрд░реНрдиреЗрд▓ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рддрдВрддреНрд░ 80386 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
  • рдкреНрд░реАрдореЗрдкреНрдЯрд┐рд╡ рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛: рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рдХреЗрд╡рд▓ рдПрдХ рд╕реАрдкреАрдпреВ рд╕рдХреНрд░рд┐рдп рд╣реЛрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдФрд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд┐рд╕реА рднреА рд╕рдордп рд╢реБрд░реВ рд╣реЛ рд╕рдХрддреА рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╕рд╛рдорд╛рдиреНрдп рддреБрд▓реНрдпрдХрд╛рд▓рди рдирд┐рдпрдо рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ: рд╕рд╛рдЭрд╛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд░рдирд╛ (рд╕реНрдкрд┐рди-рд▓реЙрдХ рдХреЗ рдмрд┐рдирд╛)ред рдПрдХ рдЪрд░рдо рдорд╛рдорд▓реЗ рдореЗрдВ, рдЗрдВрдЯрд░рдкреНрдЯ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ рд▓реЙрдХ рдХрд░рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред



рдЖрдЧреЗ рдХреА рд╣рд▓рдЪрд▓ рдХреЗ рдмрд┐рдирд╛, рджреЛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдХреЛрдб рдХреЛ рдмреЗрд╣рддрд░ рдкрдардиреАрдпрддрд╛ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рд░реВрдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рдирд┐рд░рдВрддрд░рддрд╛ рд╡рд░реНрдгреЛрдВ (\) рдХреЗ рдмрд┐рдирд╛ рдкреНрд░рддрд┐ рдкрдВрдХреНрддрд┐ рдПрдХ рддрддреНрд╡ред

рд▓рд┐рдирдХреНрд╕ 0.01
 /** include/linux/sched.h */ #define switch_to(n) { struct {long a,b;} __tmp; __asm__("cmpl %%ecx,_current\n\t" "je 1f\n\t" "xchgl %%ecx,_current\n\t" "movw %%dx,%1\n\t" "ljmp %0\n\t" "cmpl %%ecx,%2\n\t" "jne 1f\n\t" "clts\n" "1:" ::"m" (*&__tmp.a), "m" (*&__tmp.b), "m" (last_task_used_math), "d" _TSS(n), "c" ((long) task[n])); } 

рд▓рд┐рдирдХреНрд╕ 0.11
 /** include/linux/sched.h */ #define switch_to(n) { struct {long a,b;} __tmp; __asm__("cmpl %%ecx,_current\n\t" "je 1f\n\t" "movw %%dx,%1\n\t" "xchgl %%ecx,_current\n\t" "ljmp %0\n\t" "cmpl %%ecx,_last_task_used_math\n\t" "jne 1f\n\t" "clts\n" "1:" ::"m" (*&__tmp.a), "m" (*&__tmp.b), "d" (_TSS(n)), "c" ((long) task[n])); } 

рддреБрд░рдВрдд рд╣рдбрд╝рддрд╛рд▓реА рд╡рд╣ рдХрд┐рддрдирд╛ рдЫреЛрдЯрд╛ рд╣реИ! рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддрд┐ рдХреЛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЫреЛрдЯрд╛:

 #define switch_to(n) { 

рддреЛ switch_to() рдПрдХ рдореИрдХреНрд░реЛ рд╣реИред рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдПрдХ рдЬрдЧрд╣ рдкрд░ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ: schedule() рдХреА рдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ schedule() ред рдЗрд╕рд▓рд┐рдП, рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЗ рдмрд╛рдж, рдореИрдХреНрд░реЛ рд╢реЗрдбреНрдпреВрд▓рд░ рдХреНрд╖реЗрддреНрд░ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рддрд╛ рд╣реИред рдЕрдЬреНрдЮрд╛рдд рд▓рд┐рдВрдХ рдХреЗ рд╡реИрд╢реНрд╡рд┐рдХ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдПрдХ рдЪреЗрдХ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ current рдФрд░ last_task_used_math ред рдЗрдирдкреБрдЯ рддрд░реНрдХ n рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдХреА рдЕрдиреБрдХреНрд░рдо рд╕рдВрдЦреНрдпрд╛ рд╣реИ (0 рд╕реЗ 63 рддрдХ)ред

 struct {long a,b;} __tmp; 

рд╕реНрдЯреИрдХ рдкрд░ 8 рдмрд╛рдЗрдЯреНрд╕ (64 рдмрд┐рдЯреНрд╕) рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░рдЦрддрд╛ рд╣реИ, рджреЛ 4-рдмрд╛рдЗрдЯ рддрддреНрд╡реЛрдВ a рдФрд░ b рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реБрд▓рднред рд╣рдо рд▓рдВрдмреА рдЫрд▓рд╛рдВрдЧ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдЗрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдмрд╛рдЗрдЯреНрд╕ рдХреЛ рдмрд╛рдж рдореЗрдВ рд╕реЗрдЯ рдХрд░реЗрдВрдЧреЗред

 __asm__("cmpl %%ecx,_current\n\t" 

рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдЕрд╕реЗрдВрдмрд▓рд░ рдореЗрдВ рдПрдХ рд▓рдВрдмрд╛ рдЗрдирд▓рд╛рдЗрди рдмреНрд▓реЙрдХ рд╣реИред рдкрд╣рд▓рд╛ рдирд┐рд░реНрджреЗрд╢ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд▓рдХреНрд╖реНрдп рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЪрд╛рд▓реВ рд╣реИред рдпрд╣ рд╢реЗрдбреНрдпреВрд▓рд░ рд╕реЗ рд╡рд░реНрддрдорд╛рди current рдХреЗ рдореВрд▓реНрдп рдХреЗ рд╕рд╛рде рдИрд╕реАрдПрдХреНрд╕ рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдореВрд▓реНрдп рдХреА рдПрдХ рдШрдЯрд┐рдпрд╛ рддреБрд▓рдирд╛ рд╣реИред рджреЛрдиреЛрдВ рдореЗрдВ рдХреБрдЫ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ task_struct рд▓рд┐рдП рд╕рдВрдХреЗрдд рд╣реЛрддреЗ рд╣реИрдВред ECX рдореЗрдВ рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рдХреНрд╖реНрдп рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рд╣реИ: "c" ((long) task[n]) ред рддреБрд▓рдирд╛ рдкрд░рд┐рдгрд╛рдо рд╕реНрдерд┐рддрд┐ рд░рдЬрд┐рд╕реНрдЯрд░ EFLAGS рдХрд╛ рдореВрд▓реНрдп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, ZF = 1 рдпрджрд┐ рджреЛрдиреЛрдВ рдмрд┐рдВрджреБрдУрдВ рдХрд╛ рдорд┐рд▓рд╛рди рд╣реЛрддрд╛ рд╣реИ (x - x = 0)ред

 "je 1f\n\t" 

рдпрджрд┐ рдЕрдЧрд▓рд╛ рдХрд╛рд░реНрдп рд╡рд░реНрддрдорд╛рди рдПрдХ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рд╕рдВрджрд░реНрдн рдХреЛ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдЗрд╕ рдкреВрд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП (рдХреВрджрдирд╛ рдЪрд╛рд╣рд┐рдП)ред je рдирд┐рд░реНрджреЗрд╢ рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ рдХрд┐ ZF = 1. рдпрджрд┐ рдРрд╕рд╛ рд╣реИ, рддреЛ рдпрд╣ рдХреЛрдб рдореЗрдВ рдЗрд╕ рдмрд┐рдВрджреБ рдХреЗ рдмрд╛рдж рдкрд╣рд▓реЗ рд▓реЗрдмрд▓ '1' рдкрд░ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ 8 рд▓рд╛рдЗрдиреЛрдВ рд╕реЗ рдЖрдЧреЗ рд╣реИред

 "xchgl %%ecx,_current\n\t" 

рдирдП рдХрд╛рд░реНрдп рдХреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реИрд╢реНрд╡рд┐рдХ current рдХреЛ рдЕрджреНрдпрддрди рдХрд░рддрд╛ рд╣реИред ECX (рдХрд╛рд░реНрдп [n]) рд╕реЗ рд╕реВрдЪрдХ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИред рдЭрдВрдбреЗ рдЕрдкрдбреЗрдЯ рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рд╣реИрдВред

 "movw %%dx,%1\n\t" 

рд▓рдХреНрд╖реНрдп рдЪрдпрдирдХрд░реНрддрд╛ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рд╕реЗрдЧрдореЗрдВрдЯ рдЪрдпрдирдХрд░реНрддрд╛ (TSS) рдЗрдВрдбреЗрдХреНрд╕ рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рдЖрд░рдХреНрд╖рд┐рдд рд╕реНрдерд╛рди рдкрд░ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИред рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ, рдпрд╣ DX рд░рдЬрд┐рд╕реНрдЯрд░ рд╕реЗ __tmp.b рдкрд░ __tmp.b рдХреЛ __tmp.b рдХрд░рддрд╛ рд╣реИ, __tmp.b , рд╣рдорд╛рд░реА рдЖрд░рдХреНрд╖рд┐рдд 8-рдмрд╛рдЗрдЯ рд╕рдВрд░рдЪрдирд╛ рдХреЗ 8 рдореЗрдВ рд╕реЗ 5 рдмрд╛рдЗрдЯреНрд╕ред рдбреАрдПрдХреНрд╕ рдорд╛рди рджрд┐рдпрд╛ рдЧрдпрд╛ рдЗрдирдкреБрдЯ рд╣реИ: "d" (_TSS(n)) ред рдмрд╣реБ-рд╕реНрддрд░реАрдп _TSS рдореИрдХреНрд░реЛ рдПрдХ рд╡реИрдз TSS рдЦрдВрдб рдЪрдпрдирдХрд░реНрддрд╛ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореИрдВ рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж рдЪрд░реНрдЪрд╛ рдХрд░реВрдВрдЧрд╛ред рд▓рдмреНрдмреЛрд▓реБрдЖрдм рдпрд╣ рд╣реИ рдХрд┐ рджреЛ рдЙрдЪреНрдЪ рдмрд╛рдЗрдЯреНрд╕ __tmp.b рдЕрдм рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реЗрдЧрдореЗрдВрдЯ рдкреЙрдЗрдВрдЯрд░ рд╣реИред

 "ljmp %0\n\t" 

TSS рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдкрд░ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ 80386 рд╣реИред рдпрд╣ рд╕рд░рд▓ рдЫрд▓рд╛рдВрдЧ рднреНрд░рд╛рдордХ рд╣реЛ рд╕рдХрддреА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рддреАрди рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╡рд┐рдЪрд╛рд░ рд╣реИрдВ: рдкрд╣рд▓рд╛, ljmp рдПрдХ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рд▓рдВрдмреА рдЫрд▓рд╛рдВрдЧ рд╣реИ рдЬрд┐рд╕рдореЗрдВ 6-рдмрд╛рдЗрдЯ (48-рдмрд┐рдЯ) рдСрдкрд░реЗрдВрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рджреВрд╕рд░реЗ, рдСрдкрд░реЗрдВрдб% 0 рдХрд╛ рдЕрд░реНрде рд╣реИ __tmp. рдЪрд░ __tmp. ред рдЕрдВрдд рдореЗрдВ, рдЬреАрдбреАрдЯреА рдореЗрдВ рдПрдХ рдЦрдВрдб рдЪрдпрдирдХрд░реНрддрд╛ рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХрд╛ x86 рдореЗрдВ рд╡рд┐рд╢реЗрд╖ рдорд╣рддреНрд╡ рд╣реИред рдЖрдЗрдП рдЗрди рдмрд┐рдВрджреБрдУрдВ рдкрд░ рдПрдХ рдирдЬрд░ рдбрд╛рд▓рддреЗ рд╣реИрдВред

рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рджреВрд░ рдХрд╛ рд╕рдВрдХреНрд░рдордг


рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдВрджреБ рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕ рд╕рдВрдХреНрд░рдордг рдореЗрдВ 6-рдмрд╛рдЗрдЯ рдХрд╛ рд╕рдВрдЪрд╛рд▓рди рд╣реЛрддрд╛ рд╣реИред 80386 рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рдЧрд╛рдЗрдб рдиреЗ рд╕рдВрдХреНрд░рдордг рдХрд╛ рд╡рд░реНрдгрди рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:



__Tmp.a рдкрд░ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ


рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ __tmp рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рджреЛ 4-рдмрд╛рдЗрдЯ рдорд╛рди рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдФрд░ рд╕рдВрд░рдЪрдирд╛ a рдкрд░ рдЖрдзрд╛рд░рд┐рдд a ред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдо рдЗрд╕ рддрддреНрд╡ рдХреЛ 6-рдмрд╛рдЗрдЯ рдСрдкрд░реЗрдВрдб рдХреЗ рдЖрдзрд╛рд░ рдкрддреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдкреВрд░реНрдгрд╛рдВрдХ __tmp.b рдЕрдВрджрд░ рджреЛ рдмрд╛рдЗрдЯреНрд╕ рддрдХ рдкрд╣реБрдВрдЪ __tmp.b ред рдпреЗ рджреЛ рдмрд╛рдЗрдЯреНрд╕ рджреВрд░ рдкрддреЗ рдХреЗ "рд╕реЗрдЧрдореЗрдВрдЯ рд╕реЗрд▓реЗрдХреНрдЯрд░" рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИрдВред рдЬрдм рдкреНрд░реЛрд╕реЗрд╕рд░ рджреЗрдЦрддрд╛ рд╣реИ рдХрд┐ рдЬреАрдбреАрдЯреА рдореЗрдВ рд╕реЗрдЧрдореЗрдВрдЯ рдЯреАрдПрд╕рдПрд╕ рд╣реИ, рддреЛ рдСрдлрд╕реЗрдЯ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ __tmp.a рдХреЛ рдЖрд░рдВрднреАрдХреГрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛, рдХреНрдпреЛрдВрдХрд┐ __tmp.b рдЕрднреА рднреА рдкрд┐рдЫрд▓реЗ movw рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рдиреНрдп рдореВрд▓реНрдп рд╣реИред рдЖрд░реЗрдЦ рдореЗрдВ рд╕рдВрдХреНрд░рдордг рдкрддрд╛ рдЬреЛрдбрд╝реЗрдВ:



рд╣рдореЗрдВ рдХреИрд╕реЗ рдкрддрд╛ рдЪрд▓реЗрдЧрд╛ рдХрд┐ рдпрд╣ рдкрддрд╛ GDT рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ? рдореИрдВ рдХреЛрдб рдХреА рдЕрдиреНрдп рдкрдВрдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рд╡рд┐рд╡рд░рдг рдкреНрд░рдХрдЯ рдХрд░реВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╕рдВрд╕реНрдХрд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдЪрдпрдирдХрд░реНрддрд╛ рдореЗрдВ рдЪрд╛рд░ рд╢реВрдиреНрдп рдмрд┐рдЯреНрд╕ рдЬреАрдбреАрдЯреА рдЦреЛрдЬ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддреЗ рд╣реИрдВред _TSS(n) рдореИрдХреНрд░реЛ рдЗрди рдЪрд╛рд░ рд╢реВрдиреНрдп рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрддрд╛ рд╣реИред рдирд┐рдЪрд▓реЗ рджреЛ рдмрд┐рдЯ рдЦрдВрдб рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░ рд╕реНрддрд░ (00 рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХ / рдХрд░реНрдиреЗрд▓ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ), рдЕрдЧрд▓реЗ рд╢реВрдиреНрдп рдмрд┐рдЯ рдХрд╛ рдорддрд▓рдм рд╣реИ GDT рддрд╛рд▓рд┐рдХрд╛ (рдмреВрдЯ рд╕рдордп рдкрд░ GDTR рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд)ред рдЪреМрдерд╛ рд╢реВрдиреНрдп рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ рд╕реЗрдЧрдореЗрдВрдЯ рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ, рдЬреЛ рд╕рднреА TSS рдХреЛ GDT рддрд╛рд▓рд┐рдХрд╛ рдХреА рд╕рдорд╛рди рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдкрд░ рдордЬрдмреВрд░ рдХрд░рддрд╛ рд╣реИред

рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ


__tmp рдореЗрдВ рдЬрдВрдк рдПрдбреНрд░реЗрд╕ GDT рдореЗрдВ TSS рд╣реИрдВрдбрд▓ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдпрд╣ 80386 рдХреЗ рдореИрдиреБрдЕрд▓ рдореЗрдВ рдХреИрд╕реЗ рд╡рд░реНрдгрд┐рдд рд╣реИ:



рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдирд┐рдореНрди рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ:

  • рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╡рд░реНрддрдорд╛рди рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░ рд╕реНрддрд░ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИ (рд╣рдо рдХрд░реНрдиреЗрд▓ рдореЛрдб рдореЗрдВ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ)ред
  • рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ TSS рдорд╛рдиреНрдп рд╣реИ (рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП)ред
  • рдХрд╛рд░реНрдп рд░рдЬрд┐рд╕реНрдЯрд░ (TR) рдореЗрдВ рдЕрднреА рднреА рд╕рдВрдЧреНрд░рд╣реАрдд рдкреБрд░рд╛рдиреЗ TSS рдореЗрдВ рд╕рднреА рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдЪрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ EAX, ECX, EDX, EBX, ESP, EBP, ESP, ESI, EDI, ES, CS, SS, DS, FS, рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ рдЬреАрдПрд╕ рдФрд░ EFLAGSред рдИрдЖрдИрдкреА рдХреЛ рдЕрдЧрд▓реЗ рдирд┐рд░реНрджреЗрд╢ рдкрд░ рдмрдврд╝рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдмрдЪрд╛рдпрд╛ рднреА рдЬрд╛рддрд╛ рд╣реИред
  • рдирдП рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП TR рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИред
  • рд╕рднреА рд╕рд╛рдорд╛рдиреНрдп рд░рдЬрд┐рд╕реНрдЯрд░, EIP рдФрд░ PDBR (рд╕реНрд╡реИрдк рдПрдбреНрд░реЗрд╕ рд╕реНрдкреЗрд╕) рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред рдХрд╛рд░реНрдп рд╕реНрд╡рд┐рдЪ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП TS рдлреНрд▓реИрдЧ рдХреЛ CR0 рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рддреЛ, рдХреЗрд╡рд▓ рдирд┐рд░реНрджреЗрд╢ "ljmp %0\n\t" рд▓рд┐рдпрд╛ рдФрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рд╕рднреА рдЪрд░рдгреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд┐рдпрд╛ред рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред

 "cmpl %%ecx,%2\n\t" 

рд╣рдо рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдкрд┐рдЫрд▓реЗ рдХрд╛рд░реНрдп рдиреЗ рдЧрдгрд┐рддреАрдп рд╕рд╣рд╕рдВрд╕рд╛рдзрдХ рдХреЛ рдмрд╣рд╛рд▓ рдХрд┐рдпрд╛ рдерд╛ред рддрд░реНрдХ last_task_used_math рд╕реВрдЪрдХ рд╣реИред рдЯреАрдПрд╕ рдзреНрд╡рдЬ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХреЙрдкрд░рдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдПрдХ рдЕрд▓рдЧ рд╕рдВрджрд░реНрдн рд╣реИред рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред

 "jne 1f\n\t" 

рдпрджрд┐ рдЕрдВрддрд┐рдо рдХрд╛рд░реНрдп рдХреЙрдкреАрдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рдЕрдВрдд рдореЗрдВ рдЬрд╛рдПрдВред рд╣рдо рдЯреАрдПрд╕ рдзреНрд╡рдЬ рдХреЛ рдЫреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдЕрдЧрд▓реА рдмрд╛рд░ рдЬрдм рдЖрдк рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рддреЛ рдЖрдк рдЖрд▓рд╕реА рд╕рдлрд╛рдИ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред "рдЖрд▓рд╕реА," рдХреНрдпреЛрдВрдХрд┐ рд╣рдордиреЗ рдХрд╛рд░реНрдп рдХреЛ рддрдм рддрдХ рдХреЗ рд▓рд┐рдП рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдЖрд╡рд╢реНрдпрдХ рди рд╣реЛ рдЬрд╛рдПред

 "clts\n" 

рдЯреАрдПрд╕ рдзреНрд╡рдЬ рдХреЛ рд╕рд╛рдлрд╝ рдХрд░реЗрдВ рдпрджрд┐ рдЕрдВрддрд┐рдо рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдиреЗ рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрд╣рд╛рд▓ рдХрд┐рдпрд╛ред

 "1:" 

рдкреНрд░рд╕рдВрдЧ рд╕реНрд╡рд┐рдЪ рдПрдВрдб рдорд╛рд░реНрдХред рдЗрд╕ рд▓реЗрдмрд▓ рдХреЗ рд╕рднреА рдЬрдВрдк рдХреБрдЫ рдпрд╛ рд╕рднреА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВред

 ::"m" (*&__tmp.a), 

рдЗрд╕ рдЕрд╕реЗрдВрдмрд▓рд░ рдмреНрд▓реЙрдХ рдореЗрдВ рдХреЛрдИ рдЖрдЙрдЯрдкреБрдЯ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдкрд╣рд▓рд╛ рдЗрдирдкреБрдЯ (% 0) GDT рдореЗрдВ TSS рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рд╕реБрджреВрд░ рд╕реВрдЪрдХ рдХреЗ рдкрд╣рд▓реЗ рдЪрд╛рд░ рдмрд╛рдЗрдЯреНрд╕ рдХреА рд╕реНрдореГрддрд┐ рдореЗрдВ рд╕реНрдерд╛рди рд╣реИред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рдкрддреЗ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдорд╛рди рдЖрд░рдВрдн рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

 "m" (*&__tmp.b), 

рджреВрд╕рд░рд╛ рдЗрдирдкреБрдЯ (% 1) TSS рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рд╕реБрджреВрд░ рд╕реВрдЪрдХ рдХреЗ рдмрд╛рдЗрдЯреНрд╕ 5 рдФрд░ 6 рдХреА рд╕реНрдореГрддрд┐ рдореЗрдВ рд╕реНрдерд╛рди рд╣реИред рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ, рдпрд╣ рд╕реНрдерд╛рди рдореЗрдореЛрд░реА рдореЗрдВ рдЪрд╛рд░ рдмрд╛рдЗрдЯреНрд╕ рд░рдЦрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдкрд╣рд▓реЗ рджреЛ рдХреЛ рдЪреЗрдХ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

 "m" (last_task_used_math), 

рддреАрд╕рд░рд╛ рдЗрдирдкреБрдЯ (% 2) рдкреЙрдЗрдВрдЯрд░ рдХреА рдпрд╛рдж рдореЗрдВ рдЖрдЦрд┐рд░реА task_struct , рдЬрд┐рд╕рдиреЗ task_struct рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрд╣рд╛рд▓ рдХрд┐рдпрд╛ред

 "d" (_TSS(n)), 

рдЪреМрдерд╛ рдЗрдирдкреБрдЯ (% 3 / %% edx) GDT рдореЗрдВ TSS рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рд╕реЗрдЧрдореЗрдВрдЯ рдЪрдпрдирдХрд░реНрддрд╛ рдХрд╛ рдкрддрд╛ рд╣реИред рдЖрдЗрдП рдореИрдХреНрд░реЛ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:

 #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) #define FIRST_TSS_ENTRY 4 

рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдкрд╣рд▓рд╛ TSS рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ 4 рд╡рд╛рдВ рд░рд┐рдХреЙрд░реНрдб рд╣реИ (рдЗрдВрдбреЗрдХреНрд╕ рдХреА рд╢реБрд░реБрдЖрдд рд╕реЗрдЧрдореЗрдВрдЯ рдЪрдпрдирдХрд░реНрддрд╛ рдХреЗ 4 рдмрд┐рдЯ рдХреЗ рд╕рд╛рде рд╣реЛрддреА рд╣реИ)ред рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рдж рдХреЗ рдЯреАрдПрд╕рдПрд╕ рдкреНрд░рддреНрдпреЗрдХ рджреВрд╕рд░реЗ рдЬреАрдбреАрдЯреА рд░рд┐рдХреЙрд░реНрдб рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░ рд▓реЗрддрд╛ рд╣реИ: 4, 6, 8, рдЖрджрд┐ред рдкрд╣рд▓реЗ рдЖрда рдХрд╛рд░реНрдп рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреЗ рд╣реИрдВ:

рдЯрд╛рд╕реНрдХ #16-рдмрд┐рдЯ рдЦрдВрдб рдЪрдпрдирдХрд░реНрддрд╛
00000000000100 0 00
10000000000110 0 00
20000000001000 0 00
30000000001010 0 00
40000000001100 0 00
50000000001110 0 00
60000000010000 0 00
70000000010010 0 00

рдкрддрд╛ рдмрд┐рдЯреНрд╕ рдХреЛ рдлрд╝реАрд▓реНрдб рдкреНрд░рд╛рд░реВрдк рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ 80386 рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:



рдЪрд╛рд░ рдХрдо рд╕реЗ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯ рд╣рдореЗрд╢рд╛ рд╢реВрдиреНрдп рд╣реЛрддреЗ рд╣реИрдВ, рдЬреЛ рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХ рдореЛрдб, рдЬреАрдбреАрдЯреА рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИ, рдФрд░ рдЬреАрдбреАрдЯреА рд╕реВрдЪрдХрд╛рдВрдХ рдХреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЛ рднреА рдмрд╛рдзреНрдп рдХрд░рддрд╛ рд╣реИред

 "c" ((long) task[n])); 

рдЕрдВрддрд┐рдо рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ (% 4 /% ecx) рдирдП рдЯрд╛рд╕реНрдХ_рд╕реНрдЯреНрд░реИрдХ рдХрд╛ рдПрдХ рд╕рдВрдХреЗрддрдХ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рд╕реНрд╡рд┐рдЪ рдХрд░рддреЗ рд╣реИрдВред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рд╕реЗ рдареАрдХ рдкрд╣рд▓реЗ %% ecx рдорд╛рди рдкрд┐рдЫрд▓реЗ рдХрд╛рд░реНрдп рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИред

0.01 рдФрд░ 0.11 рдХреЗ рдмреАрдЪ рдЕрдВрддрд░


рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рдмреАрдЪ рджреЛ рдЕрдВрддрд░ рд╣реИрдВред рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рд╕рд░рд▓ рдХреЛрдб рд╕рдлрд╛рдИ рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛ рдЖрдВрд╢рд┐рдХ рддреНрд░реБрдЯрд┐ рд╕реБрдзрд╛рд░ рд╣реИред

  • _last_task_used_math рдЗрдирдкреБрдЯ рдЪрд░ рдХреЗ рд░реВрдк _last_task_used_math рд╣рдЯрд╛ рджрд┐рдпрд╛ _last_task_used_math рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рддреАрдХ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╡реИрд╢реНрд╡рд┐рдХ рджрд╛рдпрд░реЗ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИред рд╕рдВрдмрдВрдзрд┐рдд рддреБрд▓рдирд╛ рдСрдкрд░реЗрд╢рди рдХреЛ рд╕реАрдзрд╛ рд▓рд┐рдВрдХ рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
  • xchgl рдирд┐рд░реНрджреЗрд╢ рдХреЛ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ ( ljmp ) рдХреЗ рдХрд░реАрдм рд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП xchgl рд╕рд╛рде рд╕реНрд╡реИрдк рдХрд┐рдпрд╛ рдЧрдпрд╛ред рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпреЗ рдСрдкрд░реЗрд╢рди рдкрд░рдорд╛рдгреБ рдирд╣реАрдВ рд╣реИрдВ: рдпрд╣ рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ xchgl рдФрд░ ljmp рдмреАрдЪ рдПрдХ рд╡реНрдпрд╡рдзрд╛рди рдЙрддреНрдкрдиреНрди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдЧрд▓рдд current рдХрд╛рд░реНрдп рдФрд░ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХрд╛рд░реНрдп рдХреЗ рдмрд┐рдирд╛ рд╕рд╣реЗрдЬреЗ рдЧрдП рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рдФрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЛ рдЬрдиреНрдо рджреЗрдЧрд╛ред рдЗрди рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдпрд╣ рд╕реНрдерд┐рддрд┐ рдмрд╣реБрдд рдХрдо рд╣реЛ рдЬрд╛рддреА рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдЪрд▓рдиреЗ рд╡рд╛рд▓реА рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ рдпрд╣ "рдмрд╣реБрдд рдХрдо рд╕рдВрднрд╛рд╡рдирд╛" рд╣реИ - "рдЕрдкрд░рд┐рд╣рд╛рд░реНрдп" рдХрд╛ рдПрдХ рдкрд░реНрдпрд╛рдпред

рд▓рд┐рдирдХреНрд╕ 1.x: рдЕрд╡рдзрд╛рд░рдгрд╛ рдХрд╛ рдкреНрд░рдорд╛рдг


0.11 рдФрд░ 1.0 рдХреЗ рдмреАрдЪ рдПрдХ рд╡рд░реНрд╖ рдореЗрдВ рд▓рдЧрднрдЧ 20 рдкреИрдЪ рдЬрд╛рд░реА рдХрд┐рдП рдЧрдП рдереЗред рдЕрдзрд┐рдХрд╛рдВрд╢ рдкреНрд░рдпрд╛рд╕ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдФрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдбреНрд░рд╛рдЗрд╡рд░реЛрдВ, рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдкрд░ рдХреЗрдВрджреНрд░рд┐рдд рдереЗред рдХрд╛рд░реНрдпреЛрдВ рдХреА рдЕрдзрд┐рдХрддрдо рд╕рдВрдЦреНрдпрд╛ 128 рд╣реЛ рдЧрдИ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдореЗрдВ рдХрдИ рдореВрд▓рднреВрдд рдкрд░рд┐рд╡рд░реНрддрди рдирд╣реАрдВ рд╣реБрдП рд╣реИрдВред

рд▓рд┐рдирдХреНрд╕ 1.0


рд▓рд┐рдирдХреНрд╕ 1.0 рдЕрднреА рднреА рдПрдХ рд╣реА рд╕реАрдкреАрдпреВ рдкрд░ рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рдЪрд▓рддрд╛ рд╣реИ, рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдПред



рд▓рд┐рдирдХреНрд╕ 1.0
 /** include/linux/sched.h */ #define switch_to(tsk) __asm__("cmpl %%ecx,_current\n\t" "je 1f\n\t" "cli\n\t" "xchgl %%ecx,_current\n\t" "ljmp %0\n\t" "sti\n\t" "cmpl %%ecx,_last_task_used_math\n\t" "jne 1f\n\t" "clts\n" "1:" : /* no output */ :"m" (*(((char *)&tsk->tss.tr)-4)), "c" (tsk) :"cx") 

рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкрд░рд┐рд╡рд░реНрддрди рдпрд╣ рдерд╛ рдХрд┐ рдЗрдирдкреБрдЯ рддрд░реНрдХ рдХрд╛рд░реНрдп_ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рд╕рдВрдЦреНрдпрд╛ рд╕реВрдЪрдХрд╛рдВрдХ рдирд╣реАрдВ рд░рд╣ рдЧрдпрд╛ рд╣реИред рдЕрдм switch_to() рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдПрдХ рдирдП рдХрд╛рд░реНрдп рдореЗрдВ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИред рддреЛ рдЖрдк __tmp рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп TSS рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реАрдзрд╛ рд▓рд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдЗрдП рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддрд┐ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВред

 #define switch_to(tsk) 

рдЗрдирдкреБрдЯ рдЕрдм рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдХреЛ task_struct рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреЙрдЗрдВрдЯрд░ рд╣реИред

 "__asm__("cmpl %%ecx,_current\n\t" 

рдмрджрд▓рд╛ рдирд╣реАрдВ рдЧрдпрд╛ред рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЗрдирдкреБрдЯ рдХрд╛рд░реНрдп рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЪрд╛рд▓реВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХрд┐рд╕реА рд╕реНрд╡рд┐рдЪ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред

 "je 1f\n\t" 

рдмрджрд▓рд╛ рдирд╣реАрдВ рдЧрдпрд╛ред рд╕реНрд╡рд┐рдЪ рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХрд░рдирд╛ рдЫреЛрдбрд╝ рджреЗрдВред

 "cli\n\t" 

рд╡реНрдпрд╡рдзрд╛рдиреЛрдВ рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдХрд╛рд░реНрдп рдФрд░ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмреАрдЪ рдЯрд╛рдЗрдорд░ (рдпрд╛ рдХреЛрдИ рдФрд░) рджреБрд░реНрдШрдЯрдирд╛рдЧреНрд░рд╕реНрдд рди рд╣реЛред рдпрд╣ рд░реБрдХрд╛рд╡рдЯ рдмреИрдВрд╣рдорд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджреЛ рдирд┐рд░реНрджреЗрд╢ (рдЫрджреНрдо) рдкрд░рдорд╛рдгреБ рдмрдирд╛рдХрд░ рд╢реБрд░реБрдЖрддреА рдХрд░реНрдиреЗрд▓ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред

 "xchgl %%ecx,_current\n\t" "ljmp %0\n\t" 

рдХреЛрдИ рдкрд░рд┐рд╡рд░реНрддрди рдирд╣реАрдВ: рдирдП рдХрд╛рд░реНрдп рдХреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдиреЗ рдФрд░ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд░реНрддрдорд╛рди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕реНрд╡реИрдк рдХрд░реЗрдВред

 "sti\n\t" 

рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ рдкрд░ рд╡рд╛рдкрд╕ рд╡реНрдпрд╡рдзрд╛рдиред

 "cmpl %%ecx,_last_task_used_math\n\t" "jne 1f\n\t" "clts\n" "1:" 

рд▓рд┐рдирдХреНрд╕ 0.11 рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╕рдм рдХреБрдЫ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реИред рдЯреАрдПрд╕ рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкрд┐рдЫрд▓реЗ рдХрд╛рд░реНрдп рд╕реЗ рдЧрдгрд┐рддреАрдп рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд╕рдорд╛рд╢реЛрдзрди рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддрд╛ рд╣реИред

 : /* no output */ 

рдЗрд╕ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ рдХрд╛ рдХреЛрдИ рдЖрдЙрдЯрдкреБрдЯ рдирд╣реАрдВ рд╣реИ - рдХрд░реНрдиреЗрд▓ рдХреЗ рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреА рдХрдореА рд╕реЗ рдХреЛрдИ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд╛рд░рд╛рдЬ рдерд╛ред

 :"m" (*(((char *)&tsk->tss.tr)-4)), 

рдПрдХ рдирдП рдХрд╛рд░реНрдп рдХреЗ TSS рд╡рд┐рд╡рд░рдгрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдЦрдВрдб рдЪрдпрдирдХрд░реНрддрд╛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЕрдм task_struct рд╕реВрдЪрдХ рд╕реЗ рд╕реАрдзреЗ рдкрд╣реБрдБрдЪрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред tss.tr рддрддреНрд╡ рдореЗрдВ GDT / TSS рдореЗрдореЛрд░реА рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ _TSS (task_number) рд╣реИ рдЬреЛ рдХрд░реНрдиреЗрд▓ рдореЗрдВ 1.0 рд╕реЗ рдкрд╣рд▓реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╣рдо рдЕрднреА рднреА 4 рдмрд╛рдЗрдЯреНрд╕ рд╕реЗ рд╡рд╛рдкрд╕ рдЖрддреЗ рд╣реИрдВ рдФрд░ рд╢реАрд░реНрд╖ рджреЛ рдмрд╛рдЗрдЯреНрд╕ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП 6-рдмрд╛рдЗрдЯ рд╕реЗрдЧрдореЗрдВрдЯ рдЪрдпрдирдХрд░реНрддрд╛ рдХреЛ рд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВред рдордЬрд╛ рдЖ рдЧрдпрд╛!

 "c" (tsk) 

рд▓рдЧрднрдЧ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд - рдЕрдм рд╣рдо рд╕реАрдзреЗ рд╕реВрдЪрдХ рдХреЛ рд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЗрдВрдбреЗрдХреНрд╕ рдХреА рддрд▓рд╛рд╢ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред

 :"cx") 

рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдИрд╕реАрдПрдХреНрд╕ рд░рдЬрд┐рд╕реНрдЯрд░ рдХреЛ рдмреНрд▓реЙрдХ рдХрд░рддрд╛ рд╣реИред

рд▓рд┐рдирдХреНрд╕ 1.3


рдХрд░реНрдиреЗрд▓ рдЕрдм рдХрдИ рдирдП рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ: рдЕрд▓реНрдлрд╛, рдПрдордЖрдЗрдкреАрдПрд╕ рдФрд░ рд╕реНрдкрд╛рд░реНрдХред рдЗрд╕рд▓рд┐рдП, switch_to() рдЪрд╛рд░ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рдВрд╕реНрдХрд░рдг рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдПрдХ рдХрд░реНрдиреЗрд▓ рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддреЗ рд╕рдордп рд╢рд╛рдорд┐рд▓ рд╣реИред рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреЛрдб рдХреЛ рдХрд░реНрдиреЗрд▓ рд╕реЗ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдХрд╣реАрдВ рдФрд░ x86 рд╕рдВрд╕реНрдХрд░рдг рджреЗрдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рд▓рд┐рдирдХреНрд╕ 1.3
 /** include/asm-i386/system.h */ #define switch_to(tsk) do { __asm__("cli\n\t" "xchgl %%ecx,_current\n\t" "ljmp %0\n\t" "sti\n\t" "cmpl %%ecx,_last_task_used_math\n\t" "jne 1f\n\t" "clts\n" "1:" : /* no output */ :"m" (*(((char *)&tsk->tss.tr)-4)), "c" (tsk) :"cx"); /* Now maybe reload the debug registers */ if(current->debugreg[7]){ loaddebug(0); loaddebug(1); loaddebug(2); loaddebug(3); loaddebug(6); } } while (0) 

рдХреБрдЫ рдЫреЛрдЯреЗ рдкрд░рд┐рд╡рд░реНрддрди: рдкреВрд░реЗ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЛ рдирдХрд▓реА рдбреВ-рдЯрд╛рдЗрдо рд▓реВрдк рдореЗрдВ рд▓рдкреЗрдЯрд╛ рдЧрдпрд╛ рд╣реИред Feykov рдХреНрдпреЛрдВрдХрд┐ рд╡рд╣ рдХрднреА рдирд╣реАрдВ рджреЛрд╣рд░рд╛рддрд╛ рд╣реИред рд╕реА рдореЗрдВ рдПрдХ рдирдпрд╛ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреА рдЬрд╛рдВрдЪ рд╕реА рдореЗрдВ sheduler рдХреЛрдб рдХреЗ рд▓рд┐рдП switch_to() рд╕реЗ рдЪрд▓реА рдЧрдИ рд╣реИред рдХреБрдЫ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ C рдХреЛрдб рд╕реЗ switch_to () рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╕рдВрднрд╡рддрдГ рдЙрдиреНрд╣реЗрдВ рдЕрд▓рдЧ рдХрд░рдиреЗ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдПред рдЖрдЗрдП рдмрджрд▓рд╛рд╡реЛрдВ рдХреЛ рджреЗрдЦреЗрдВред

 #define switch_to(tsk) do { 

рдЕрдм switch_to() рдПрдХ рдбреВ- switch_to() 0) рд▓реВрдк рдореЗрдВ рд▓рд┐рдкрдЯрд╛ рд╣реБрдЖ рд╣реИред рдпрд╣ рдбрд┐рдЬрд╝рд╛рдЗрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд░реЛрдХрддрд╛ рд╣реИ рдпрджрд┐ рд╕реНрдерд┐рддрд┐ (рдпрджрд┐ рдХреЛрдИ рд╣реЛ) рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдореИрдХреНрд░реЛ рдХрдИ рдмрдпрд╛рдиреЛрдВ рддрдХ рдлреИрд▓рддрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рдореЗрдВ, рдпрд╣ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╢реЗрдбреНрдпреВрд▓рд░ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рдореБрдЭреЗ рд╕рдВрджреЗрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдХреЛрдб рдХреЗ рд╕рдВрдкрд╛рджрди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИ, рдмрд╕ рдорд╛рдорд▓реЗ рдореЗрдВред рдореЗрд░рд╛ рдЕрдиреБрдорд╛рди:

1.3 рдореЗрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдпреЛрдЬрдирд╛рдХрд╛рд░
 ...within schedule()... if (current == next) return; kstat.context_swtch++; switch_to(next); 

рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рд╡рд┐рдХрд▓реНрдк рдЬреЛ switch_to рдХреЛ рддреЛрдбрд╝рддрд╛ рд╣реИ ()
 ...within schedule()... if (current != next) switch_to(next); /* do-while(0) 'captures' entire * block to ensure proper parse */ 


 __asm__("cli\n\t" "xchgl %%ecx,_current\n\t" "ljmp %0\n\t" "sti\n\t" "cmpl %%ecx,_last_task_used_math\n\t" "jne 1f\n\t" "clts\n" "1:" : /* no output */ :"m" (*(((char *)&tsk->tss.tr)-4)), "c" (tsk) :"cx"); 

рд▓рд┐рдирдХреНрд╕ 1.0 рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХреЛрдИ рдкрд░рд┐рд╡рд░реНрддрди рдирд╣реАрдВред рдлрд┐рд░ рднреА, рдЗрдВрдЯрд░рдкреНрдЯ рдХреЛ рдХрд░рдВрдЯ рд╕реЗ * task_struct рд╕реНрд╡реИрдк рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдХреНрд╖рдо рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдлрд┐рд░ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЪреЗрдХ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

 /* Now maybe reload the debug registers */ if(current->debugreg[7]){ 

рд╕рдХреНрд░рд┐рдп ptrace рдХреЗ рд▓рд┐рдП рдПрдХ рдирдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдбрд┐рдмрдЧрд┐рдВрдЧ рдирд┐рдпрдВрддреНрд░рдг рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ (рдпрд╣рд╛рдБ рдЧреИрд░-рд╢реВрдиреНрдп рдкрддреЗ рдХрд╛ рдЕрд░реНрде рд╣реИ рд╕рдХреНрд░рд┐рдп ptrace)ред рдбреАрдмрдЧ рдЯреНрд░реИрдХрд┐рдВрдЧ switch_to() рдореЗрдВ рдЪрд▓реА рдЧрдИ рд╣реИред рдареАрдХ рдЙрд╕реА рдХреНрд░рдо C рдХрд╛ рдЙрдкрдпреЛрдЧ 1.0 рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рдереЗ рдХрд┐: 1) рдбрд┐рдмрдЧрд┐рдВрдЧ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ 2 рдХреЗ рдЬрд┐рддрдирд╛ рд╕рдВрднрд╡ рд╣реЛ рдЙрддрдирд╛ рдХрд░реАрдм рд╣реИ) рд╕реНрд╡рд┐рдЪ_рдЯреЛ schedule() рдореЗрдВ рдирд╡реАрдирддрдо рд╣реИ schedule() ред

 loaddebug(0); loaddebug(1); loaddebug(2); loaddebug(3); 

рд╕рд╣реЗрдЬреЗ рдЧрдП ptrace рд╕реНрдерд┐рддрд┐ рд╕реЗ рдбреАрдмрдЧ рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред

 loaddebug(6); 

рд╕рд╣реЗрдЬреЗ рдЧрдП ptrace рд╕реНрдерд┐рддрд┐ рд╕реЗ рдбреАрдмрдЧ рдирд┐рдпрдВрддреНрд░рдг рд░рдЬрд┐рд╕реНрдЯрд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред

 } while (0) 

switch_to() рдмреНрд▓реЙрдХ рдХреЛ рдмрдВрдж рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╕реНрдерд┐рддрд┐ рд╣рдореЗрд╢рд╛ рд╕рдорд╛рди рд╣реЛрддреА рд╣реИ, рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдкрд╛рд░реНрд╕рд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЖрдзрд╛рд░ рдЗрдХрд╛рдИ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реЗрддрд╛ рд╣реИ рдЬреЛ schedule() рдореЗрдВ рдкрдбрд╝реЛрд╕реА рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ schedule() ред рдЕрдВрдд рдореЗрдВ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ - рдпрд╣ рдореИрдХреНрд░реЛ рдХреЙрд▓ рдХреЗ рдмрд╛рдж рдЦрдбрд╝рд╛ рд╣реЛрддрд╛ рд╣реИ: switch_to(next); ред

рд▓рд┐рдирдХреНрд╕ 2.0: рдЙрдореНрдореАрджрд╡рд╛рд░ (1996)


рдЬреВрди 1996 рдореЗрдВ, рдХрд░реНрдиреЗрд▓ рдХреЛ рд╕рдВрд╕реНрдХрд░рдг 2.0 рдореЗрдВ рдЕрджреНрдпрддрди рдХрд┐рдпрд╛ рдЧрдпрд╛, рдЗрд╕ рдкреНрд░рдореБрдЦ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рддрд╣рдд 15-рд╡рд░реНрд╖реАрдп рдУрдбрд┐рд╕реА рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЧрдпрд╛, рдЬреЛ рд╡реНрдпрд╛рдкрдХ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рд╕рдорд░реНрдерди рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реБрдЖред 2.x рдореЗрдВ, рдХрд░реНрдиреЗрд▓ рдореЗрдВ рд▓рдЧрднрдЧ рд╕рднреА рдореВрд▓рднреВрдд рдкреНрд░рдгрд╛рд▓рд┐рдпрд╛рдБ рдЖрдореВрд▓ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рддреА рд╣реИрдВред 2.6 рд╕реЗ рдкрд╣рд▓реЗ рд╕рднреА рдЫреЛрдЯреА рд░рд┐рд▓реАрдЬ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╕рдВрд╕реНрдХрд░рдг 2.6 рдХреЛ рдЗрддрдиреЗ рд▓рдВрдмреЗ рд╕рдордп рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдЕрд▓рдЧ рдЕрдиреБрднрд╛рдЧ рдХреЗ рдпреЛрдЧреНрдп рд╣реИред

рд▓рд┐рдирдХреНрд╕ 2.0


рд▓рд┐рдирдХреНрд╕ 2.0 рдХреА рд╢реБрд░реБрдЖрдд рдХрд╛рд░реНрдбрд┐рдирд▓ рдЗрдиреЛрд╡реЗрд╢рди рд╕реЗ рд╣реБрдИ: рдорд▓реНрдЯреАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ ! рджреЛ рдпрд╛ рдЕрдзрд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдПрдХ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ / рдХрд░реНрдиреЗрд▓ рдХреЛрдб рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдкрд░рд┐рд╢реЛрдзрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЗрдВ рдЕрдм рдПрдХ рд╕рдорд░реНрдкрд┐рдд рдмрд╛рдзрд╛ рдирд┐рдпрдВрддреНрд░рдХ, APIC рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╡реНрдпрд╡рдзрд╛рди рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдкрд░ рдЕрд▓рдЧ рд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЯрд╛рдЗрдорд░ рд░реБрдХрд╛рд╡рдЯ рдЬреИрд╕реЗ рддрдВрддреНрд░реЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рд╡реНрдпрд╡рдзрд╛рдиреЛрдВ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдирд╛ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ)ред рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдореБрд╢реНрдХрд┐рд▓ рд╣реИ, рдЦрд╛рд╕рдХрд░ рдЬрдм рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрдбрд╝реЗ рдФрд░ рдЕрд╕рдВрдмрдВрдзрд┐рдд рдХреЛрдб рдЖрдзрд╛рд░ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИред рд▓рд┐рдирдХреНрд╕ 2.0 рдПрдХ рдмрдбрд╝реЗ рдХрд░реНрдиреЗрд▓ рд▓реЙрдХ (BKL) рдХреЗ рд▓рд┐рдП рдиреАрдВрд╡ рджреЗрддрд╛ рд╣реИ ... рдЖрдкрдХреЛ рдХрд╣реАрдВ рд╕реЗ рд╢реБрд░реВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ switch_to() рджреЛ рд╕рдВрд╕реНрдХрд░рдг рд╣реИрдВ switch_to() : Linux 1.x рд╕реЗ рдПрдХрд▓-рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕рдВрд╕реНрдХрд░рдг (UP) рдФрд░ рд╕рдордорд┐рддреАрдп рдорд▓реНрдЯреАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ (SMP) рдХреЗ рд▓рд┐рдП рдирдпрд╛ рдЙрдиреНрдирдд рд╕рдВрд╕реНрдХрд░рдгред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдкреБрд░рд╛рдиреЗ рдХреЛрдб рдореЗрдВ рдмрджрд▓рд╛рд╡ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╡рд╣рд╛рдВ рд╕реЗ рдХреБрдЫ рдмрджрд▓рд╛рд╡ рдПрд╕рдПрдордкреА рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рднреА рд╢рд╛рдорд┐рд▓ рд╣реИрдВред

рд▓рд┐рдирдХреНрд╕ 2.0.1: рдпреВрдиреАрдкреНрд░реЛрд╕реЗрд╕рд░ рд╡рд░реНрдЬрди (рдпреВрдкреА)




рд▓рд┐рдирдХреНрд╕ 2.0.1 (рдпреВрдкреА)
 /** include/asm-i386/system.h */ #else /* Single process only (not SMP) */ #define switch_to(prev,next) do { __asm__("movl %2,"SYMBOL_NAME_STR(current_set)"\n\t" "ljmp %0\n\t" "cmpl %1,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" "jne 1f\n\t" "clts\n" "1:" : /* no outputs */ :"m" (*(((char *)&next->tss.tr)-4)), "r" (prev), "r" (next)); /* Now maybe reload the debug registers */ if(prev->debugreg[7]){ loaddebug(prev,0); loaddebug(prev,1); loaddebug(prev,2); loaddebug(prev,3); loaddebug(prev,6); } } while (0) #endif 

рджреЛ рдмрджрд▓рд╛рд╡ рддреБрд░рдВрдд рд╕реНрдкрд╖реНрдЯ рд╣реИрдВ:

  • рдпреВ switch_to()рдХрд╛ рдПрдХ рдирдпрд╛ рддрд░реНрдХ рд╣реИ: рдЬрд┐рд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реЗ *task_structрд╣рдо рд╕реНрд╡рд┐рдЪ рдХрд░ рд░рд╣реЗ рд╣реИрдВред
  • рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ рдореЗрдВ рд╡рд░реНрдгреЛрдВ рдХреЗ рд╕рд╣реА рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдореИрдХреНрд░реЛред

рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣, рдЪрд▓реЛ рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рд╕рд╛рде рдЪрд▓рддреЗ рд╣реИрдВ рдФрд░ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рддреЗ рд╣реИрдВред

 #define switch_to(prev,next) do { 

рддрд░реНрдХ prevрдЙрд╕ рдХрд╛рд░реНрдп рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо ( *task_struct) рд╕реЗ рд╕реНрд╡рд┐рдЪ рдХрд░ рд░рд╣реЗ рд╣реИрдВ ред рд╣рдо рдЕрднреА рднреА рдореИрдХреНрд░реЛ рдХреЛ рдбреВ-рдЯрд╛рдЗрдо (0) рд▓реВрдк рдореЗрдВ рд▓рдкреЗрдЯ рд░рд╣реЗ рд╣реИрдВ рддрд╛рдХрд┐ рдореИрдХреНрд░реЛ рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рд╕рд┐рдВрдЧрд▓-рд▓рд╛рдЗрди рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдорд┐рд▓ рд╕рдХреЗред

 __asm__("movl %2,"SYMBOL_NAME_STR(current_set)"\n\t" 

рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╕рдХреНрд░рд┐рдп рдХрд╛рд░реНрдп рдХреЛ рдирдП рдЪрдпрдирд┐рдд рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд░реВрдк рд╕реЗ рд╕рдорддреБрд▓реНрдп рд╣реИ xchgl %%ecx,_current, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ SYMBOL_NAME_STRрдЕрд╕реЗрдВрдмрд▓реА рд╡рд░реНрдгреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдХрд╛рд░реНрдп_рд╕реНрдЯреНрд░реЛрдХ рдФрд░ рдПрдХ рдореИрдХреНрд░реЛ ( ) рдХреА рдПрдХ рд╕рд░рдгреА рд╣реИ ред рдЗрд╕рдХреЗ рд▓рд┐рдП рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрдпреЛрдВ рдХрд░реЗрдВ? рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдХреБрдЫ рдХреЛрдбрд╛рдВрддрд░рдХреЛрдВ (рдЬреАрдПрдПрд╕) рдХреЛ рдЪрд░ рдирд╛рдо рд╕реА рдХреЗ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ (_) рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЕрдиреНрдп рдХреЛрдбрд╛рдВрддрд░рдХреЛрдВ рдХреА рдпрд╣ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред рдПрдХ рдХрдиреНрд╡реЗрдВрд╢рди рдХреЛ рд╣рд╛рд░реНрдб рдбреНрд░рд╛рдЗрд╡ рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдЗрд╕реЗ рдЕрдкрдиреЗ рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рд╕реЗрдЯ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

 "ljmp %0\n\t" "cmpl %1,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" "jne 1f\n\t" "clts\n" "1:" : /* no outputs */ :"m" (*(((char *)&next->tss.tr)-4)), 

рдХреЛрдИ рдмрджрд▓рд╛рд╡ рдирд╣реАрдВ рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣рдордиреЗ рдмрд╛рдд рдирд╣реАрдВ рдХреА рд╣реИред

 "r" (prev), "r" (next)); 

рдЕрдм рд╣рдо рдЗрдирд▓рд╛рдЗрди рдЕрд╕реЗрдВрдмрд▓рд░ рдХреЗ рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рджреЛрдиреЛрдВ рдХрд╛рд░реНрдп рдХрд░рддреЗ рд╣реИрдВред рдПрдХ рдорд╛рдореВрд▓реА рдмрджрд▓рд╛рд╡ рдпрд╣ рд╣реИ рдХрд┐ рдЕрдм рд░рдЬрд┐рд╕реНрдЯрд░ рдХреЗ рдХрд┐рд╕реА рднреА рдЙрдкрдпреЛрдЧ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред рдпрд╣ рдкрд╣рд▓реЗ nextECX рдореЗрдВ рдПрдирдХреЛрдбреЗрдб рдерд╛ред

 /* Now maybe reload the debug registers */ if(prev->debugreg[7]){ loaddebug(prev,0); loaddebug(prev,1); loaddebug(prev,2); loaddebug(prev,3); loaddebug(prev,6); } } while (0) 

рд╕рдм рдХреБрдЫ рдареАрдХ рд╡реИрд╕рд╛ рд╣реА рд╣реИ рдЬреИрд╕рд╛ рдХрд┐ рдХрд░реНрдиреЗрд▓ 1.3 рдореЗрдВред

рд▓рд┐рдирдХреНрд╕ 2.0.1: рдорд▓реНрдЯреАрдкреНрд░реЛрд╕реЗрд╕рд░ рд╡рд░реНрдЬрди (рдПрд╕рдПрдордкреА)




рд▓рд┐рдирдХреНрд╕ 2.0.1 (рдПрд╕рдПрдордкреА)
 /** include/asm-i386/system.h */ #ifdef __SMP__ /* Multiprocessing enabled */ #define switch_to(prev,next) do { cli(); if(prev->flags&PF_USEDFPU) { __asm__ __volatile__("fnsave %0":"=m" (prev->tss.i387.hard)); __asm__ __volatile__("fwait"); prev->flags&=~PF_USEDFPU; } prev->lock_depth=syscall_count; kernel_counter+=next->lock_depth-prev->lock_depth; syscall_count=next->lock_depth; __asm__("pushl %%edx\n\t" "movl "SYMBOL_NAME_STR(apic_reg)",%%edx\n\t" "movl 0x20(%%edx), %%edx\n\t" "shrl $22,%%edx\n\t" "and $0x3C,%%edx\n\t" "movl %%ecx,"SYMBOL_NAME_STR(current_set)"(,%%edx)\n\t" "popl %%edx\n\t" "ljmp %0\n\t" "sti\n\t" : /* no output */ :"m" (*(((char *)&next->tss.tr)-4)), "c" (next)); /* Now maybe reload the debug registers */ if(prev->debugreg[7]){ loaddebug(prev,0); loaddebug(prev,1); loaddebug(prev,2); loaddebug(prev,3); loaddebug(prev,6); } } while (0) 

рдХреНрдпрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рдордЭ рдореЗрдВ рдирд╣реАрдВ рдЖ рд░рд╣рд╛ рд╣реИ? рдореИрдВ рдХрд╣рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рдмрд╛рдж рдореЗрдВ рдпрд╣ рдмреЗрд╣рддрд░ рд╣реЛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдПрд╕рдПрдордкреА рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЕрдВрддрд░рд┐рдХреНрд╖ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдЕрдм рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рддрд╛рд░реЛрдВ рдХреА рд╕реВрдЪреА рдирд╣реАрдВ рджреВрдВрдЧрд╛ред

рдПрд╕рдПрдордкреА рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рд▓рд┐рдП рддреАрди рдЬреЛрдбрд╝: 1) рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рдПрдХ рдПрдХрд▓ рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХрдИ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЙрд╕реЗ рдмрджрд▓рдирд╛; 2) рд▓реЙрдХ рдХреА рдЧрд╣рд░рд╛рдИ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдирд╛, рдХреНрдпреЛрдВрдХрд┐ рдХрд░реНрдиреЗрд▓ рд▓реЙрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╣реИ; 3) рд╡рд░реНрддрдорд╛рди * task_struct рдХреЗ рд▓рд┐рдП CPU ID рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП APIC рд╕реЗ рд▓рд┐рдВрдХ рдХрд░реЗрдВред

 if(prev->flags&PF_USEDFPU) 

рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ рдЬрд┐рд╕ рдХрд╛рд░реНрдп рдХреЛ рд╣рдо рд╕реНрд╡рд┐рдЪ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рд╡рд╣ рдПрдХ рдХреЙрдкреАрдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рд╣рд╛рдВ, рддреЛ рдЖрдкрдХреЛ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдПрдлрдкреАрдпреВ рдореЗрдВ рд╕рдВрджрд░реНрдн рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

 __asm__ __volatile__("fnsave %0":"=m" (prev->tss.i387.hard)); 

TSS рдХреЛ FPU рд░рд╛рдЬреНрдп рдмрдЪрд╛рддрд╛ рд╣реИред FNSAVE рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдкрд╡рд╛рдж рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред __volatile__рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝рд░ рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рд╕реЗ рдЗрд╕ рдирд┐рд░реНрджреЗрд╢ рдХреА рд░рдХреНрд╖рд╛ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред

 __asm__ __volatile__("fwait"); 

рд╕реАрдкреАрдпреВ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ рдЬрдмрдХрд┐ рдПрдлрдкреАрдпреВ рдкрд┐рдЫрд▓реЗ рдмрдЪрдд рдХреЗ рд╕рд╛рде рд╡реНрдпрд╕реНрдд рд╣реИред

 prev->flags&=~PF_USEDFPU; 

рдЗрд╕ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдзреНрд╡рдЬ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рддрд╛ рд╣реИ, рд╣рдореЗрд╢рд╛ рд╢реВрдиреНрдп рд╣реЛрддрд╛ рд╣реИред

 prev->lock_depth=syscall_count; 

рдХрд┐рд╕реА рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдХрд░реНрдиреЗрд▓ рд▓реЙрдХрд┐рдВрдЧ рдХреЗ рдиреЗрд╕реНрдЯреЗрдб рдЙрдкрдпреЛрдЧ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИред

 kernel_counter+=next->lock_depth-prev->lock_depth; 

рд╡реИрд╢реНрд╡рд┐рдХ рдХрд░реНрдиреЗрд▓ рд▓реЙрдХ рдХрд╛рдЙрдВрдЯрд░ рдХреЛ рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЛ рдШрдЯрд╛ рджреЗрддрд╛ рд╣реИред рдкреНрд░рднрд╛рд╡реА рд░реВрдк рд╕реЗ рдЕрдм рдирд┐рд╖реНрдХреНрд░рд┐рдп рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рд╕реЗ рд▓реЙрдХ рдХреЛ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдирдпрд╛ рдХрд╛рд░реНрдп рдЙрд╕ рд╕реНрдерд╛рди рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦ рд╕рдХрддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдпрд╣ рд░реБрдХрд╛ рдерд╛ред

 syscall_count=next->lock_depth; 

рдХрд┐рд╕реА рдирдП рдХрд╛рд░реНрдп рдХреА рд▓реЙрдХ рд╕реНрдерд┐рддрд┐ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП рдЬрд╣рд╛рдВ рд╡рд╣ рд╕рдордп рдХреЗ рдЖрдЦрд┐рд░реА рдЦрд┐рдВрдЪрд╛рд╡ рдореЗрдВ рдЫреВрдЯ рдЧрдИред

 __asm__("pushl %%edx\n\t" 

рд╣рдо EDX рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕рдХрд╛ рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп рд░рдЦреЗрдВрдЧреЗред

 "movl "SYMBOL_NAME_STR(apic_reg)",%%edx\n\t" 

EDIC I / O рдкрддреЗ рдХреЛ EDX рдкрд░ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИред рд╣рдореЗрдВ рд╕реАрдкреАрдпреВ рдЖрдИрдбреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдкреАрдЖрдИрд╕реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдирд╣реАрдВ рдкрддрд╛ рд╣реИ рдХрд┐ рдХреМрди рд╕рд╛ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред apic_regOS рдЖрд░рдВрднреАрдХрд░рдг рдХреЗ рджреМрд░рд╛рди рдкреНрд░рд╕рд╛рд░рдгред

 "movl 0x20(%%edx), %%edx\n\t" 

EDX рдореЗрдВ APIC рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рд░рдЬрд┐рд╕реНрдЯрд░ рдХреЗ рдорд╛рди рдХреЛ рд╣рдЯрд╛рддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЖрдИрдбреА рдмрд┐рдЯреНрд╕ 24-27 рдореЗрдВ рд╣реИред



 "shrl $22,%%edx\n\t" 

APIC ID рдХреЛ 2-5 рдмрд┐рдЯреНрд╕ рдкрд░ рд╢рд┐рдлреНрдЯ рдХрд░рддрд╛ рд╣реИред

 "and $0x3C,%%edx\n\t" 

рдмрд┐рдЯреНрд╕ 2-5 рдореЗрдВ рдХреЗрд╡рд▓ APIC ID рдХреЛ рдорд╛рд╕реНрдХ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ CPU рдирдВрдмрд░ * 4 рдирд┐рдХрд▓ рдЬрд╛рддрд╛ рд╣реИред

 "movl %%ecx,"SYMBOL_NAME_STR(current_set)"(,%%edx)\n\t" 

рд╡рд░реНрддрдорд╛рди рд╕реАрдкреАрдпреВ рдХреЗ рдХрд╛рд░реНрдп рд╕реВрдЪрдХ рдХреЛ рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдЕрджреНрдпрддрди рдХрд░рддрд╛ рд╣реИред рдпреВрдкреА рд╕рдВрд╕реНрдХрд░рдг рдиреЗ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП ECX рдХреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрдкрдпреЛрдЧ рдХреЛ рдкрд╣рд▓реЗ рд╣реА рд╣рдЯрд╛ рджрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрднреА рднреА SMP рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред EDX рдмрд┐рдЯреНрд╕ рдореЗрдВ CPU рд╕рдВрдЦреНрдпрд╛ 2-5, 4 рд╕реЗ рдЧреБрдгрд╛ рдХрд░рддрд╛ рд╣реИ, рдкреЙрдЗрдВрдЯрд░ рдЖрдХрд╛рд░ рдХреЛ _current_set рд╕реЗ рдСрдлрд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдХреЗрд▓ рдореЗрдВ рд╣реИред

 "popl %%edx\n\t" 

рд╣рдореЗрдВ рдИрдбреАрдПрдХреНрд╕ рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реЗ рдкрд╣рд▓реЗ рдЙрд╕ рдореВрд▓реНрдп рдХреЛ рдмрд╣рд╛рд▓ рдХрд░реЗрдВрдЧреЗред

рд╢реЗрд╖ рд░реЗрдЦрд╛рдПрдБ рд╕рдорд╛рди рд╣реИрдВред

рд▓рд┐рдирдХреНрд╕ 2.2 (1999)


рд▓рд┐рдирдХреНрд╕ 2.2 рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреЗ рд▓рд╛рдпрдХ рдерд╛: рдпрд╣рд╛рдВ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдЖрдпрд╛ рдерд╛ ! рд╣рдо рдЕрднреА рднреА TSS рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯрд╛рд╕реНрдХ рд░рдЬрд┐рд╕реНрдЯрд░ (TR) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдПрд╕рдПрдордкреА рдФрд░ рдпреВрдкреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдПрдХреАрдХреГрдд рдПрдлрдкреАрдпреВ рд░рд╛рдЬреНрдп рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рд╕рдВрдпреБрдХреНрдд рд╣реИрдВред рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдЕрдм рд╕реАред рд▓рд┐рдирдХреНрд╕ 2.2.0 рдХреЛрдб



(рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ) рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
 /** include/asm-i386/system.h */ #define switch_to(prev,next) do { unsigned long eax, edx, ecx; asm volatile("pushl %%ebx\n\t" "pushl %%esi\n\t" "pushl %%edi\n\t" "pushl %%ebp\n\t" "movl %%esp,%0\n\t" /* save ESP */ "movl %5,%%esp\n\t" /* restore ESP */ "movl $1f,%1\n\t" /* save EIP */ "pushl %6\n\t" /* restore EIP */ "jmp __switch_to\n" "1:\t" "popl %%ebp\n\t" "popl %%edi\n\t" "popl %%esi\n\t" "popl %%ebx" :"=m" (prev->tss.esp),"=m" (prev->tss.eip), "=a" (eax), "=d" (edx), "=c" (ecx) :"m" (next->tss.esp),"m" (next->tss.eip), "a" (prev), "d" (next)); } while (0) 

рдпрд╣ рдирдпрд╛ рдПрдХ рдЖрдо switch_to()рддреМрд░ рдкрд░ рдкрд┐рдЫрд▓реЗ рд╕рднреА рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рд╕реЗ рдЕрд▓рдЧ рд╣реИ: рдпрд╣ рд╕рд░рд▓ рд╣реИ! рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ рдореЗрдВ, рд╣рдо рд╕реНрдЯреИрдХ рдФрд░ рдирд┐рд░реНрджреЗрд╢ рдмрд┐рдВрджреБ (рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХрд╛рд░реНрдп 1 рдФрд░ 2) рд╕реНрд╡реИрдк рдХрд░рддреЗ рд╣реИрдВред C ( __switch_to()) рдХреЛрдб рдореЗрдВ рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред

 asm volatile("pushl %%ebx\n\t" "pushl %%esi\n\t" "pushl %%edi\n\t" "pushl %%ebp\n\t" 

рд╕реНрдЯреЛрд░ EBX, ESI, EDI рдФрд░ EBP рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдвреЗрд░ рдореЗрдВ рд╣рдо рд╕реНрд╡реИрдк рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред (... рдХреНрдпреЛрдВ EBX?)

 "movl %%esp,%0\n\t" /* save ESP */ "movl %5,%%esp\n\t" /* restore ESP */ 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдкреБрд░рд╛рдиреА рдФрд░ рдирдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдмреАрдЪ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░реНрд╕ рд╕реНрд╡реИрдк рдХрд░рддреЗ рд╣реИрдВред рдкреБрд░рд╛рдиреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдСрдкрд░реЗрдВрдб% 0 ( prev->tss.esp) рд╣реИ, рдЬрдмрдХрд┐ рдирдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ % 5 ( next->tss.esp) рд╣реИред

 "movl $1f,%1\n\t" /* save EIP */ 

рд╕рдВрджрд░реНрдн рд╡рд╛рдкрд╕ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рдЕрдЧрд▓реЗ рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢ рд╕реВрдЪрдХ рдХреЗ рдореВрд▓реНрдп рдХреЛ рд╕рд╣реЗрдЬрдирд╛ред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдирд┐рдореНрди рдХрдерди рдХрд╛ рдорд╛рди рдПрдХ рд▓реЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ 1:

 "pushl %6\n\t" /* restore EIP */ 

рдирдП рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рд░реНрджреЗрд╢ рддреИрдпрд╛рд░ рдХрд░реЗрдВред рдЪреВрдВрдХрд┐ рд╣рдордиреЗ рдЕрднреА рдПрдХ рдирдП рд╕реНрдЯреИрдХ рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЖрдИрдкреА рдирдП рдХрд╛рд░реНрдп рдХреЗ TSS рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рд╕реНрдЯреИрдХ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред рдирд┐рд╖реНрдкрд╛рджрди рд╕реА тАЛтАЛрдХреЛрдб рдХреЗ 'рд░рд┐рдЯ' рдХреЗ рдмрд╛рдж рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдерди рд╕реЗ рд╢реБрд░реВ рд╣реЛрдЧрд╛ рдЬрд┐рд╕реЗ рд╣рдо рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВред

 "jmp __switch_to\n" 

рд╣рдо рдЕрдкрдиреЗ рдирдП рдФрд░ рдмреЗрд╣рддрд░ рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ (рдиреАрдЪреЗ рджреЗрдЦреЗрдВ)ред

 "popl %%ebp\n\t" "popl %%edi\n\t" "popl %%esi\n\t" "popl %%ebx" 

рд╣рдо рдПрдХ рдирдП рд╕рдордп рдЕрдВрддрд░рд╛рд▓ рдореЗрдВ рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕рдВрднрд╡рддрдГ рд░рд┐рд╡рд░реНрд╕ рдСрд░реНрдбрд░ рдореЗрдВ рд╕реНрдЯреИрдХ рд╕реЗ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рд▓рд┐рдирдХреНрд╕ 2.2.0 (C)
 /** arch/i386/kernel/process.c */ void __switch_to(struct task_struct *prev, struct task_struct *next) { /* Do the FPU save and set TS if it wasn't set before.. */ unlazy_fpu(prev); gdt_table[next->tss.tr >> 3].b &= 0xfffffdff; asm volatile("ltr %0": :"g" (*(unsigned short *)&next->tss.tr)); asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs)); asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs)); /* Re-load LDT if necessary */ if (next->mm->segments != prev->mm->segments) asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt)); /* Re-load page tables */ { unsigned long new_cr3 = next->tss.cr3; if (new_cr3 != prev->tss.cr3) asm volatile("movl %0,%%cr3": :"r" (new_cr3)); } /* Restore %fs and %gs. */ loadsegment(fs,next->tss.fs); loadsegment(gs,next->tss.gs); if (next->tss.debugreg[7]){ loaddebug(next,0); loaddebug(next,1); loaddebug(next,2); loaddebug(next,3); loaddebug(next,6); loaddebug(next,7); } } 

рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдореЗрдВ, TSS рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдкреБрд░рд╛рдиреЗ рд╕рдВрдХреНрд░рдордг рдХреЛ рдирдП C: рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╕рдВрдХреНрд░рдордг рджреНрд╡рд╛рд░рд╛ рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ __switch_to()ред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рд╕реА рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕рдореЗрдВ рдХрдИ рдкрд░рд┐рдЪрд┐рдд рдШрдЯрдХ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдЬреИрд╕реЗ рдбрд┐рдмрдЧ рд░рдЬрд┐рд╕реНрдЯрд░ред C рдкрд░ рдЬрд╛рдиреЗ рд╕реЗ рдЖрдк рдЙрдиреНрд╣реЗрдВ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рдФрд░ рднреА рдХрд░реАрдм рд▓реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред

 unlazy_fpu(prev); 

рд╣рдо рдПрдлрдкреАрдпреВ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдпрджрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдЪрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЕрдм рдпрд╣ рд╣рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рд╣реЛрддрд╛ рд╣реИ рдЬреЛ FPU рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рдлрд╛рдИ рдЕрдм рдЖрд▓рд╕реА рдирд╣реАрдВ рд╣реИред рдкреНрд░рдХреНрд░рд┐рдпрд╛ 2.0.1 рд╕реЗ рдПрд╕рдПрдордкреА рджрд┐рдирдЪрд░реНрдпрд╛ рдХреЗ рд╕рдорд╛рди рд╣реИ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕реНрд╡рдЪреНрдЫ рдореИрдХреНрд░реЛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдореИрдиреБрдЕрд▓ рдЯреАрдПрд╕ рдЯреНрдпреВрдирд┐рдВрдЧ рд╢рд╛рдорд┐рд▓ рд╣реИред

 gdt_table[next->tss.tr >> 3].b &= 0xfffffdff; 

рднрд╡рд┐рд╖реНрдп рдХреЗ рдХрд╛рд░реНрдп рд╡рд┐рд╡рд░рдгрдХ рдХреЗ рд▓рд┐рдП BUSY рдмрд┐рдЯ рдХреЛ рд╕рд╛рдлрд╝ рдХрд░рддрд╛ рд╣реИред GDT рдХреЛ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред tss.trрдХрд╛рд░реНрдп рдЦрдВрдб рдЪрдпрдирдХрд░реНрддрд╛ рдХрд╛ рдорд╛рди рд╕рдорд╛рд╣рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдирд┐рдЪрд▓реЗ рддреАрди рдмрд┐рдЯреНрд╕ рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЗрдВрдбреЗрдХреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрди рдмрд┐рдЯреНрд╕ рдХреЛ рд╢рд┐рдлреНрдЯ рдХрд░рддреЗ рд╣реИрдВред рджреВрд╕рд░рд╛ TSS рдмрд╛рдЗрдЯ рдмрд┐рдЯ 10 рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред



 asm volatile("ltr %0": :"g" (*(unsigned short *)&next->tss.tr)); 

рдЯрд╛рд╕реНрдХ рд░рдЬрд┐рд╕реНрдЯрд░ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЗ рд╕рд╛рде рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдЦрдВрдб рдЪрдпрдирдХрд░реНрддрд╛ рдХреЛ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

 asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs)); asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs)); 

рдкрд┐рдЫрд▓реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП FS рдФрд░ GS рдЦрдВрдб рд░рдЬрд┐рд╕реНрдЯрд░ TSS рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИрдВред рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдореЗрдВ, рдпрд╣ рдЪрд░рдг рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЕрдм рд╣рдореЗрдВ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдХреНрдпреЛрдВ? рд▓рд┐рдирдХреНрд╕ рдПрдлрдПрд╕ рдФрд░ рдЬреАрдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░рддрд╛ рд╣реИ?

рд▓рд┐рдирдХреНрд╕ 2.2 (1999) рдкрд░ рдХреЛрдИ рд╕реНрдкрд╖реНрдЯ рдЙрддреНрддрд░ рдирд╣реАрдВ рд╣реИред рдХреЗрд╡рд▓ рдпрд╣ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдЙрдиреНрд╣реЗрдВ рд╕рд╣реЗрдЬрдирд╛ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рд╡реЗ рд╕реБрд▓рдн рд░рд╣реЗрдВред рдХрд░реНрдиреЗрд▓ рдореЛрдб рдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░реНрдиреЗрд▓-рдореЛрдб рдХреЛрдб рдЗрди рдЦрдВрдбреЛрдВ рдХреЛ "рдЙрдзрд╛рд░" рджреЗрдЧрд╛ред рд╕рд╛рдЙрдВрдб рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рдбреНрд░рд╛рдЗрд╡рд░ рдРрд╕рд╛ рд╣реА рдХрд░рддреЗ рд╣реИрдВред рд╣рд╛рд▓ рд╣реА рдореЗрдВ (~ 2.6 рдЖрдЧреЗ) рдПрдлрдПрд╕ рдФрд░ рдЬреАрдПрд╕ рдЕрдХреНрд╕рд░ рд╕реНрдерд╛рдиреАрдп рд╕реНрдЯреНрд░реАрдо рд╕реНрдЯреЛрд░реЗрдЬ рдФрд░ рдбреЗрдЯрд╛ рдХреНрд╖реЗрддреНрд░ рдкреНрд░рддрд┐ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВред

 if (next->mm->segments != prev->mm->segments) asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt)); 

рд╕реНрдерд╛рдиреАрдп рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдЦрдВрдбреЛрдВ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ рд╡реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреБрд░рд╛рдиреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдЕрдиреБрд░реВрдк рдирд╣реАрдВ рд╣реИрдВред рдпрд╣ LDT рд░рдЬрд┐рд╕реНрдЯрд░ рд▓реЛрдб рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

 if (new_cr3 != prev->tss.cr3) asm volatile("movl %0,%%cr3": :"r" (new_cr3)); 

рдХрд┐рд╕реА рдирдП рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рд╡рд░реНрдЪреБрдЕрд▓ рдореЗрдореЛрд░реА рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЕрджреНрдпрддрди рдХрд░рддрд╛ рд╣реИред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, CR3 рд░рдЬрд┐рд╕реНрдЯрд░ рд╕реЗрдЯ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдирдП рд╕рдВрджрд░реНрдн рдореЗрдВ рдореЗрдореЛрд░реА рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреГрд╖реНрдареЛрдВ рдХреА рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╣реИред

 loadsegment(fs,next->tss.fs); loadsegment(gs,next->tss.gs); 

рдирдП рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдлрдПрд╕ рдФрд░ рдЬреАрдПрд╕ рдХреЛ рдмрд╣рд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рдпрд╣ рд╕рд╣реА рд╕рдВрд░реЗрдЦрдг рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╢реВрдиреНрдп рдЦрдВрдб рд▓реЛрдб рд╣реЛрддрд╛ рд╣реИред

 loaddebug(prev,7); 

рдЕрдВрдд рдореЗрдВ, рдбреАрдмрдЧ рдХрдВрдЯреНрд░реЛрд▓ рд░рдЬрд┐рд╕реНрдЯрд░ рдЕрдм рдЯреАрдПрд╕рдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдЧреНрд░рд╣реАрдд рдФрд░ рд╕реНрд╡рд┐рдЪ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдкрд╣рд▓реЗ, рдпрд╣ рд░рдЬрд┐рд╕реНрдЯрд░ рдХреЗрд╡рд▓ рдЪреЗрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рд▓рд┐рдирдХреНрд╕ 2.4 (2001)


рд╡рд░реНрдЬрди 2.4 рдиреЗ рдХрд░реНрдиреЗрд▓ рдереНрд░реЗрдбреНрд╕ рдФрд░ рдЯрд╛рд╕реНрдХ рдХреНрдпреВ рдЬреИрд╕реЗ рдХрдИ рдирдП рдлреАрдЪрд░реНрд╕ рдкреЗрд╢ рдХрд┐рдПред рд╢реЗрдбреНрдпреВрд▓рд░ рдореЗрдВ рдЗрд╕рдХреЗ рдФрд░ рдХреБрдЫ рдмрджрд▓рд╛рд╡реЛрдВ рдХреЗ рдмрд╛рд╡рдЬреВрдж, рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рд╕рдВрд╕реНрдХрд░рдг 2.2 рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдирд╣реАрдВ рдмрджрд▓рд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЗрд╕рдиреЗ рд╕рднреА рд░рдЬрд┐рд╕реНрдЯрд░ рдбреЗрдЯрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдкрдХреНрд╖ рдореЗрдВ рдЯреАрдЖрд░ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рд╣реИред рдореИрдВ рдЕрдиреМрдкрдЪрд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдЗрд╕реЗ "рдЕрдВрддрд┐рдо рд▓рд┐рдЧреЗрд╕реА рдХрд░реНрдиреЗрд▓" рдХрд╣рддрд╛ рд╣реВрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╕рднреА рднрд╡рд┐рд╖реНрдп рдХреЗ рд░рд┐рд▓реАрдЬ 64-рдмрд┐рдЯ x86 рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред



рд▓рд┐рдирдХреНрд╕ 2.4.0 (рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ)
 /** include/asm-i386/system.h */ #define switch_to(prev,next,last) do { asm volatile("pushl %%esi\n\t" "pushl %%edi\n\t" "pushl %%ebp\n\t" "movl %%esp,%0\n\t" /* save ESP */ "movl %3,%%esp\n\t" /* restore ESP */ "movl $1f,%1\n\t" /* save EIP */ "pushl %4\n\t" /* restore EIP */ "jmp __switch_to\n" "1:\t" "popl %%ebp\n\t" "popl %%edi\n\t" "popl %%esi\n\t" :"=m" (prev->thread.esp),"=m" (prev->thread.eip), "=b" (last) :"m" (next->thread.esp),"m" (next->thread.eip), "a" (prev), "d" (next), "b" (prev)); } while (0) 

2.4 рдХрд░реНрдиреЗрд▓ рдореЗрдВ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗрд╡рд▓ рдХреБрдЫ рдорд╛рдореВрд▓реА рдмрджрд▓рд╛рд╡ рдХрд░рддрд╛ рд╣реИ: EBX рдХреЛ рдЕрдм рдзрдХреНрдХрд╛ рдирд╣реАрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИред рдПрдХ рдирдпрд╛ рдЗрдирдкреБрдЯ рддрд░реНрдХ рд╕рд╛рдордиреЗ рдЖрдпрд╛ lastрд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╕рдорд╛рди рдорд╛рди рд╣реИ prevред рдпрд╣ рдИрдмреАрдПрдХреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░реЗрд╖рд┐рдд рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

 :"=m" (prev->thread.esp),"=m" (prev->thread.eip), :"m" (next->thread.esp),"m" (next->thread.eip), 

I / O рдСрдкрд░реЗрдВрдб рдЕрдм рдХрд░реНрдиреЗрд▓ рдереНрд░реЗрдбреНрд╕ рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдХ / рдирд┐рд░реНрджреЗрд╢ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдЯреАрдПрд╕рдПрд╕ рд╕реЗ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд▓рд┐рдирдХреНрд╕ 2.4.0 (C)
 /** arch/i386/kernel/process.c */ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; struct tss_struct *tss = init_tss + smp_processor_id(); unlazy_fpu(prev_p); tss->esp0 = next->esp0; asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); /* Restore %fs and %gs. */ loadsegment(fs, next->fs); loadsegment(gs, next->gs); /* Now maybe reload the debug registers */ if (next->debugreg[7]){ loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); loaddebug(next, 3); /* no 4 and 5 */ loaddebug(next, 6); loaddebug(next, 7); } if (prev->ioperm || next->ioperm) { if (next->ioperm) { memcpy(tss->io_bitmap, next->io_bitmap, IO_BITMAP_SIZE*sizeof(unsigned long)); tss->bitmap = IO_BITMAP_OFFSET; } else tss->bitmap = INVALID_IO_BITMAP_OFFSET; } } 

рд╕реА рдХреЛрдб рд╡рд╛рд▓реЗ рд╣рд┐рд╕реНрд╕реЗ рдиреЗ рдХреБрдЫ рдЪреАрдЬреЗрдВ рдмрджрд▓ рджреА рд╣реИрдВред TR рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд╛ рдХреЛрдИ рдЙрд▓реНрд▓реЗрдЦ рдЧрд╛рдпрдм рд╣реЛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рд╡рд░реНрддрдорд╛рди рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рд╕рдХреНрд░рд┐рдп TSS рдХреЛ рд╕реАрдзреЗ рдмрджрд▓ рджреЗрддреЗ рд╣реИрдВред рдЗрдирд▓рд╛рдЗрди рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЗ рд░реВрдк рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдп TSS рдбреЗрдЯрд╛ рдХреЛ рдереНрд░реЗрдб_рд╕реНрдЯреНрд░реЛрдХ рдХреЗ рдЕрдВрджрд░ task_struct рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рд╕рдХреНрд░рд┐рдп CPU GDT рд╕реЗ рд╕рдорд░реНрдкрд┐рдд TSS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рд╕реАрдзреЗ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИред

 void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) 

рдкрд┐рдЫрд▓реЗ рдФрд░ рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рдВрдХреЗрдд рдкрд░ рдПрдХ рдкреНрд░рддреНрдпрдп рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ _pред рдпрд╣ рдПрдХ рдЫреЛрдЯреА рд▓реЗрдХрд┐рди рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрддрд┐ рд╕реВрдХреНрд╖реНрдо рдЕрдВрддрд░ рд╡рдЬрд╣ рд╕реЗ рд╣реИ prevрдФрд░ nextрдЧрд┐рд░реА рдзрд╛рдЧреЗ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛ рд░рд╣рд╛ рд╣реИред

 struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; 

рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП TSS рдбреЗрдЯрд╛ рдХреЗ рдмрд┐рдВрджреБ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред

 tss->esp0 = next->esp0; 

рдирдП рдХрд╛рд░реНрдп рд╕реЗ рдСрдлрд╕реЗрдЯ рдХреЗ рд╕рд╛рде рд╕реНрдЯреИрдХ рдСрдлрд╝рд╕реЗрдЯ рд░рд┐рдВрдЧ 0 рдХреА рдЬрдЧрд╣ред рдЬрдм рддрдХ рдпрд╣ рдкреГрд╖реНрда рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдкреБрдирдГ рд▓реЛрдб рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рди рд╣реЛ рдЬрд╛рдП ...

 asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); 

рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдлрдПрд╕ рдФрд░ рдЬреАрдПрд╕ рдХреА рдмрдЪрддред рдЗрди рдЦрдВрдбреЛрдВ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдЕрднреА рднреА рд╕рдордЭ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИ, рд▓реЗрдХрд┐рди рд╡реЗ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдирддреАрдЬрддрди, рд╕рдВрд╕реНрдХрд░рдг 2.6 рдореЗрдВ рд╡реЗ рд╕реНрдерд╛рдиреАрдп рдПрдлрдПрд╕: рдереНрд░реЗрдб рд╕реНрдЯреЛрд░реЗрдЬ рдФрд░ рдЬреАрдПрд╕: рдкреНрд░рддрд┐-рдкреНрд░реЛрд╕реЗрд╕рд░ рдбреЗрдЯрд╛ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред

 if (prev->ioperm || next->ioperm) { if (next->ioperm) { memcpy(tss->io_bitmap, next->io_bitmap, IO_BITMAP_SIZE*sizeof(unsigned long)); tss->bitmap = IO_BITMAP_OFFSET; 

рдЖрдЧрд╛рдореА рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рд╕рдХреНрд░рд┐рдп TSS рдореЗрдВ рдкреЛрд░реНрдЯ рдореИрдкрд┐рдВрдЧ I / O рдЕрдиреБрдорддрд┐рдпрд╛рдБ рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИред

 } else tss->bitmap = INVALID_IO_BITMAP_OFFSET; 

рдПрдХ рдЬреНрдЮрд╛рдд рдЕрдорд╛рдиреНрдп рдмрд┐рдЯрдореИрдк (0x8000) рдХреЗ рд▓рд┐рдП рд╕рдХреНрд░рд┐рдп TSS рдХреЗ рд▓рд┐рдП I / O рдЕрдиреБрдорддрд┐рдпрд╛рдБ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред

рд▓рд┐рдирдХреНрд╕ 2.6: рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ (2003)


рдЬреИрд╕реЗ рд╣реА рдХрд░реНрдиреЗрд▓ 2.5 рд╡рд┐рджрд╛ рд╣реБрдЖ, рд▓реАрдирд┐рдпрд░-рд░рди рд╢реЗрдбреНрдпреВрд▓рд░ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЙрдкрдпреЛрдЧ рдХреА рд╕реАрдорд╛ рддрдХ рдкрд╣реБрдВрдЪ рдЧрдпрд╛, рдФрд░ рдПрдПрдордбреА рдиреЗ x86 рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЬрд┐рд╕реЗ рдХрд░реНрдиреЗрд▓ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХрд╛ рддрддреНрдХрд╛рд▓ рдзреНрдпрд╛рди рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА: x86-64ред

рд▓рд┐рдирдХреНрд╕ 2.6.0


рдПрдХ рд╕реНрдерд┐рд░ рдХреНрд░рдо рдХреЗ рд╕рд╛рде рдХрд░реНрдиреЗрд▓ рдЕрдиреБрд╕реВрдЪрдХ рдХрд░реНрдиреЗрд▓ рдореЗрдВ 2.6.0 рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдкрд┐рдЫрд▓реЗ рд░реИрдЦрд┐рдХ рдЕрдиреБрд╕реВрдЪрдХ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдПрдХ рдХрджрдо рдЖрдЧреЗ рд╣реИ, рд▓реЗрдХрд┐рди 2.6.23 рдореЗрдВ рдЕрдВрддрддрдГ рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд┐рд╖реНрдкрдХреНрд╖ рдЕрдиреБрд╕реВрдЪрдХ (рд╕реАрдПрдлрдПрд╕) рджреНрд╡рд╛рд░рд╛ рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ред рджреВрд╕рд░реА рдУрд░, рдирдП 64-рдмрд┐рдЯ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдиреЗ рдЖрдЬ рддрдХ рдХреЗ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрджрд▓рд╛рд╡ рдХрд┐рдП рд╣реИрдВред

рд▓рд┐рдирдХреНрд╕ 2.6.0: i386 рд╕рдВрд╕реНрдХрд░рдг


рдпрд╣ рд▓реЗрдЦ рдореЗрдВ 32-рдмрд┐рдЯ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреА рдирд╡реАрдирддрдо рдЙрдкрд╕реНрдерд┐рддрд┐ рд╣реИред



рд▓рд┐рдирдХреНрд╕ 2.6.0 (i386 рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ)
 /** include/asm-i386/system.h */ #define switch_to(prev,next,last) do { unsigned long esi,edi; asm volatile("pushfl\n\t" "pushl %%ebp\n\t" "movl %%esp,%0\n\t" /* save ESP */ "movl %5,%%esp\n\t" /* restore ESP */ "movl $1f,%1\n\t" /* save EIP */ "pushl %6\n\t" /* restore EIP */ "jmp __switch_to\n" "1:\t" "popl %%ebp\n\t" "popfl" :"=m" (prev->thread.esp),"=m" (prev->thread.eip), "=a" (last),"=S" (esi),"=D" (edi) :"m" (next->thread.esp),"m" (next->thread.eip), "2" (prev), "d" (next)); } while (0) 


рдЪрд╛рд░ рд▓рд╛рдЗрдиреЗрдВ рд╣рдЯрд╛рдИ рдЧрдИрдВред ESI рдФрд░ EDI рдХреЛ рдкрд╣рд▓реЗ рд╕реНрдЯреИрдХ рдкрд░ рдзрдХреЗрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЕрдм I / O рдСрдкрд░реЗрдВрдб рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдзрдХреЗрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рд▓рд┐рдирдХреНрд╕ 2.6.0 (i386 C)
 /** arch/i386/kernel/process.c */ struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; int cpu = smp_processor_id(); struct tss_struct *tss = init_tss + cpu; __unlazy_fpu(prev_p); load_esp0(tss, next->esp0); /* Load the per-thread Thread-Local Storage descriptor. */ load_TLS(next, cpu); asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); /* Restore %fs and %gs if needed. */ if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) { loadsegment(fs, next->fs); loadsegment(gs, next->gs); } /* Now maybe reload the debug registers */ if (unlikely(next->debugreg[7])) { loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); loaddebug(next, 3); /* no 4 and 5 */ loaddebug(next, 6); loaddebug(next, 7); } if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { if (next->io_bitmap_ptr) { memcpy(tss->io_bitmap, next->io_bitmap_ptr, IO_BITMAP_BYTES); tss->io_bitmap_base = IO_BITMAP_OFFSET; } else tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; } return prev_p; } 

рдХреБрдЫ рджрд┐рд▓рдЪрд╕реНрдк рдмрджрд▓рд╛рд╡: рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП рдореВрд▓реНрдп рдФрд░ рдореИрдХреНрд░реЛ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ unlikely()ред рдореИрдВ [un] рдореЗрдВ рд▓рд┐рдкрдЯреЗ рдореМрдЬреВрджрд╛ рдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реВрдБрдЧрд╛, рддрд╛рдХрд┐ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рд╕рдордЭрд╛ рди рдЬрд╛рдПред рдореИрдХреНрд░реЛ рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рдХреЛ рдХреЗрд╡рд▓ рдпрд╣ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдкрд╛рдЗрдк рд▓рд╛рдЗрдирд┐рдВрдЧ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреМрди рд╕реА рдЖрдзрд╛рд░ рдЗрдХрд╛рдИ рдкрд╣рд▓реЗ рджрд┐рдЦрд╛рдИ рджреЗрдиреА рдЪрд╛рд╣рд┐рдПред

 struct task_struct *__switch_to(...) 

__switch_to рдЕрдм рдПрдХ рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рдкреЙрдЗрдВрдЯрд░ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рдпрд╣ рдХрд╣реАрдВ рднреА рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╛ рддреЛ рдкрд░рд┐рд╡рд░реНрддрди рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдпрд╛ рд╡реЗ рд╕рдореНрдореЗрд▓рди рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рдереЗред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХреНрд▓рд╛рд╕рд┐рдХ рд╕рдореНрдореЗрд▓рди рдЬрдм рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рди рд░рд╛рдЬреНрдп рдмрджрд▓рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдмрд╛рдж рдореЗрдВ рд╕рд╣реЗрдЬрдиреЗ рдФрд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд┐рдЫрд▓реА рд╕реНрдерд┐рддрд┐ рдХреЛ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред рдЬрдмрдХрд┐ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

 load_TLS(next, cpu); 

рдирдП рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП GDT рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдереНрд░реЗрдб рд╕реНрдЯреЛрд░ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИред рд▓рд┐рдирдХреНрд╕ 2.6 рд╡рд┐рд╢рд┐рд╖реНрдЯ рдзрд╛рд░рд╛ рдЦрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреАрдбреАрдЯреА рдореЗрдВ рддреАрди рдЯреАрдПрд▓рдПрд╕ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реИред рддреЛ, рдЧреНрд▓рд┐рдмрдХ рдкрд╣рд▓реЗ рдЦрдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рд╢рд░рд╛рдм - рджреВрд╕рд░рд╛ред рдЕрдм рд╣рдо рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ рд╕реНрдерд╛рдиреАрдп рдереНрд░реЗрдб рд╕реНрдЯреЛрд░ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП FS рдЦрдВрдб рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

 if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) { 

рдЕрдм рд╣рдо рдХреЗрд╡рд▓ FS рдФрд░ GS рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдпрджрд┐ рд╡реЗ рдкрд┐рдЫрд▓реЗ рдпрд╛ рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдереЗред

рд▓рд┐рдирдХреНрд╕ 2.6.0: x86_64 рд╕рдВрд╕реНрдХрд░рдг


X86_64 рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ 32-рдмрд┐рдЯ рдПрдХ рд╕реЗ рдХрд╛рдлреА рдЕрд▓рдЧ рд╣реИред рдЗрд╕ рдмрд╛рд░ рд╣рдо рд╕рд╛рд╡рдзрд╛рдиреАрдкреВрд░реНрд╡рдХ рдХреЛрдб рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░реЗрдВрдЧреЗ, рдХреНрдпреЛрдВрдХрд┐ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣рдо рдХреЗрд╡рд▓ 64-рдмрд┐рдЯ рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реЗрдВрдЧреЗред



рд▓рд┐рдирдХреНрд╕ 2.6.0 (рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдб x86_64)
 /** include/asm-x86_64/system.h */ #define SAVE_CONTEXT "pushfq ; pushq %%rbp ; movq %%rsi,%%rbp\n\t" #define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popfq\n\t" #define __EXTRA_CLOBBER ,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15" #define switch_to(prev,next,last) asm volatile(SAVE_CONTEXT "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ "call __switch_to\n\t" ".globl thread_return\n" "thread_return:\n\t" "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" "movq %P[thread_info](%%rsi),%%r8\n\t" "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" "movq %%rax,%%rdi\n\t" "jc ret_from_fork\n\t" RESTORE_CONTEXT : "=a" (last) : [next] "S" (next), [prev] "D" (prev), [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), [ti_flags] "i" (offsetof(struct thread_info, flags)), [tif_fork] "i" (TIF_FORK), [thread_info] "i" (offsetof(struct task_struct, thread_info)), [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) : "memory", "cc" __EXTRA_CLOBBER) 

рдореИрдХреНрд░реЛ рдХреЛ x86_64 рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ _switch_to(), рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдлрд┐рд░ рд╕реЗ рдЗрд╕рдХреА рд▓рд╛рдЗрдиреЛрдВ рд╕реЗ рдЧреБрдЬрд░рдирд╛ рд╣реЛрдЧрд╛ред рдХрдИ рдмрджрд▓рд╛рд╡ рдмрд╕ рдирд╛рдо рд░рдЬрд┐рд╕реНрдЯрд░ ( r..рдмрджрд▓реЗ e..) рд╣реИрдВред рдХреБрдЫ рдЕрдиреНрдп рд╕рд╣рд╛рдпрдХ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдореИрдВрдиреЗ рдКрдкрд░ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рд╣реИред

 asm volatile(SAVE_CONTEXT 

рдКрдкрд░ рджрд┐рдЦрд╛рдП рдЧрдП рд╕рд╣рд╛рдпрдХ рдореИрдХреНрд░реЛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдЯреИрдХ рдкрд░ рдХрд░реНрдиреЗрд▓ рд╕рдВрджрд░реНрдн рдмрдЪрд╛рддрд╛ рд╣реИред 32-рдмрд┐рдЯ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рдорд╛рди, рдирдП рд░рдЬрд┐рд╕реНрдЯрд░ рдирд╛рдореЛрдВ рдХреЗ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рдеред рдореИрдХреНрд░реЛ рдХреЛ RESTORE_CONTEXT рдХреЗ рд╕рд╛рде рдмрд┐рд▓реНрдЯ-рдЗрди рдЕрд╕реЗрдВрдмрд▓рд░ рдмреНрд▓реЙрдХ рдХреЗ рдЕрдВрдд рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред

 "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ 

рдкреБрд░рд╛рдиреЗ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ TSS рдореЗрдВ рд╕рд╣реЗрдЬрддрд╛ рд╣реИред рдЗрдирдкреБрдЯ рдСрдкрд░реЗрдВрдб рд╕реЗрдХреНрд╢рди рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирдИ рдиреЛрдЯреЗрд╢рди рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ: рдпрд╣ [threadrsp]task_struct рдХреЗ рдЕрдВрджрд░ thread.rsp рдХреА рдбрд╛рдпрд░реЗрдХреНрдЯ рдСрдлрд╕реЗрдЯ рд╣реИред %Pdereferences рдкреНрд░рдмрд▓: рдереНрд░реЗрдбрдкреЙрдЗрдВрдЯ рдкреЙрдЗрдВрдЯрд░ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдЕрджреНрдпрддрди SP рдареАрдХ рд╕реЗ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИред

 "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ 

рдирдП рдХрд╛рд░реНрдп рдХреЗ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред

 "call __switch_to\n\t" 

рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рднрд╛рдЧ C рдХреЛ рдЖрдордВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

 ".globl thread_return\n" 

рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рд▓реЗрдмрд▓ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ thread_returnред

 "thread_return:\n\t" 

рдХреЗ рд▓рд┐рдП рд╕рдВрдХреНрд░рдордг рдмрд┐рдВрджреБ thread_returnред рд╡рд┐рд╢реБрджреНрдз рд░реВрдк рд╕реЗ рдпрд╛рдВрддреНрд░рд┐рдХ рд░реВрдк рд╕реЗ, рдирд┐рд░реНрджреЗрд╢ рд╕реВрдЪрдХ рдХреЛ рдЕрдЧрд▓реЗ рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╛ рддреЛ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рдпрд╛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЬреИрд╕реЗ glibc)ред рдореЗрд░рд╛ рдЕрдиреБрдорд╛рди рд╣реИ рдХрд┐ pthreads рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ... рд▓реЗрдХрд┐рди рдпрд╣ рдРрд╕рд╛ рдирд╣реАрдВ рд▓рдЧрддрд╛ рд╣реИред

 "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" 

рдкреНрд░рддрд┐-рдХрд╛рд░реНрдп рдбреЗрдЯрд╛ рдХреНрд╖реЗрддреНрд░ (рдкреАрдбреАрдП) рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдХреЗ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХрд╛рдВрдХ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рдХрд░реНрдиреЗрд▓ рдореЛрдб рдореЗрдВ, рдЬреАрдПрд╕ рдХреЛ рд╣рдореЗрд╢рд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

 "movq %P[thread_info](%%rsi),%%r8\n\t" 

рд╕рдВрд░рдЪрдирд╛ thread_infoрдХреЛ r8 рдореЗрдВ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд▓рд┐рдирдХреНрд╕ 2.6 рдХреЗ рд▓рд┐рдП рдирдпрд╛ рд╣реИ, рдФрд░ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдПрдХ рд╣рд▓реНрдХрд╛ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ task_structрдЬреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕реНрдЯреИрдХ рдкрд░ рдлрд┐рдЯ рдмреИрдарддрд╛ рд╣реИред

 "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" 

CF рдореЗрдВ TIF_FORK рдмрд┐рдЯ рдорд╛рди рд╕рд╣реЗрдЬрддрд╛ рд╣реИ thread_info->flagsрдФрд░ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдмрд┐рдЯ рдХреЛ рд░реАрд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИред рдХреБрдЫ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЗ рдмрд╛рдж, рдпрд╣ рдмрд┐рдЯ рдХрд╛рдВрдЯрд╛ / рдХреНрд▓реЛрдирд┐рдВрдЧ рдХреЗ рдмрд╛рдж рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ ret_from_fork рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

 "movq %%rax,%%rdi\n\t" 

task_structRDI рдХреЛ рдкрд┐рдЫрд▓реА рд╕реНрдЯреНрд░реАрдо рдмрдЪрд╛рддрд╛ рд╣реИ ред EAX рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдЕрдВрддрд┐рдо рдирд┐рд░реНрджреЗрд╢ C рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реИ __switch_to, рдЬреЛ prevEAX рдкрд░ рд▓реМрдЯрддрд╛ рд╣реИред

 "jc ret_from_fork\n\t" 

рдпрджрд┐ рдпрд╣ рдзрд╛рдЧрд╛ рдПрдХ рддрд╛рдЬрд╝рд╛ рдХрд╛рдВрдЯрд╛ / рдХреНрд▓реЛрди рд╣реИ, рддреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП ret_from_fork рдкрд░ рдЬрд╛рдПрдВред

 : "=a" (last) 

рдкрд┐рдЫрд▓реА рдзрд╛рд░рд╛ EAX рдкрд░ рд╡рд╛рдкрд╕ рдЖ рдЧрдИ рд╣реИред

 : [next] "S" (next), [prev] "D" (prev), [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), [ti_flags] "i" (offsetof(struct thread_info, flags)), [tif_fork] "i" (TIF_FORK), [thread_info] "i" (offsetof(struct task_struct, thread_info)), [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) 

рдЗрдирд▓рд╛рдЗрди рдЕрд╕реЗрдВрдмрд▓рд░ рдХреЗ рд▓рд┐рдП рдЗрдирдкреБрдЯ рд▓рд┐рдВрдХред рдЙрдирдореЗрдВ рд╕реЗ рдЬреНрдпрд╛рджрд╛рддрд░ рдСрдлрд╕реЗрдЯ рдХреЗ рд╕рд╛рде рдкреНрд░рддреНрдпрдХреНрд╖ рдСрдкрд░реЗрдВрдб рд╣реИрдВред рдКрдкрд░ рд╣рдо рдкрд╣рд▓реЗ рд╣реА рдЙрдирдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднрд╛рдЧ рдЪреБрдХреЗ рд╣реИрдВред

 : "memory", "cc" __EXTRA_CLOBBER) 

рд▓рд┐рдирдХреНрд╕ 2.6.0 (x86_64 C)
 /** arch/x86_64/kernel/process.c */ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; int cpu = smp_processor_id(); struct tss_struct *tss = init_tss + cpu; unlazy_fpu(prev_p); tss->rsp0 = next->rsp0; asm volatile("movl %%es,%0" : "=m" (prev->es)); if (unlikely(next->es | prev->es)) loadsegment(es, next->es); asm volatile ("movl %%ds,%0" : "=m" (prev->ds)); if (unlikely(next->ds | prev->ds)) loadsegment(ds, next->ds); load_TLS(next, cpu); /* Switch FS and GS. */ { unsigned fsindex; asm volatile("movl %%fs,%0" : "=g" (fsindex)); if (unlikely(fsindex | next->fsindex | prev->fs)) { loadsegment(fs, next->fsindex); if (fsindex) prev->fs = 0; } /* when next process has a 64bit base use it */ if (next->fs) wrmsrl(MSR_FS_BASE, next->fs); prev->fsindex = fsindex; } { unsigned gsindex; asm volatile("movl %%gs,%0" : "=g" (gsindex)); if (unlikely(gsindex | next->gsindex | prev->gs)) { load_gs_index(next->gsindex); if (gsindex) prev->gs = 0; } if (next->gs) wrmsrl(MSR_KERNEL_GS_BASE, next->gs); prev->gsindex = gsindex; } /* Switch the PDA context. */ prev->userrsp = read_pda(oldrsp); write_pda(oldrsp, next->userrsp); write_pda(pcurrent, next_p); write_pda(kernelstack, (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); /* Now maybe reload the debug registers */ if (unlikely(next->debugreg7)) { loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); loaddebug(next, 3); /* no 4 and 5 */ loaddebug(next, 6); loaddebug(next, 7); } /* Handle the IO bitmap */ if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { if (next->io_bitmap_ptr) { memcpy(tss->io_bitmap, next->io_bitmap_ptr, IO_BITMAP_BYTES); tss->io_bitmap_base = IO_BITMAP_OFFSET; } else { tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; } } return prev_p; } 

рд╕рдВрд╕реНрдХрд░рдг x86_64 рдореЗрдВ, C рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЛрдб рдореЗрдВ рдХрдИ рдмрджрд▓рд╛рд╡ рдЬреЛрдбрд╝реЗ рдЧрдП рд╣реИрдВред рдореИрдВ рд╕рд╛рдзрд╛рд░рдг рдХреЗрд╕ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдирд╣реАрдВ рджреЛрд╣рд░рд╛рдКрдВрдЧрд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, EAX рдХреЛ RAX рдХрд╛ рдирд╛рдо рджреЗрдирд╛)ред

 asm volatile("movl %%es,%0" : "=m" (prev->es)); if (unlikely(next->es | prev->es)) loadsegment(es, next->es); 

рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП ES рд╕реЗрдЧрдореЗрдВрдЯ рдмрдЪрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдирдпрд╛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИред

 asm volatile ("movl %%ds,%0" : "=m" (prev->ds)); if (unlikely(next->ds | prev->ds)) loadsegment(ds, next->ds); 

рдХрд┐рд╕реА рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рдбреЗрдЯрд╛ рдЦрдВрдб рдмрдЪрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдПрдХ рдирдпрд╛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИред

 unsigned fsindex; asm volatile("movl %%fs,%0" : "=g" (fsindex)); if (unlikely(fsindex | next->fsindex | prev->fs)) { loadsegment(fs, next->fsindex); if (fsindex) prev->fs = 0; } 

FS рдЦрдВрдб рдХреЛ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИ fsindex, рдФрд░ рдлрд┐рд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдПрдХ рдирдП рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП FS рд▓реЛрдб рдХрд░рддрд╛ рд╣реИред рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдпрджрд┐ рдХрд┐рд╕реА рдкреБрд░рд╛рдиреЗ рдпрд╛ рдирдП рдХрд╛рд░реНрдп рдореЗрдВ рдПрдлрдПрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрдз рдореВрд▓реНрдп рд╣реИ, рддреЛ рдЙрд╕рдХреЗ рд╕реНрдерд╛рди рдкрд░ рдХреБрдЫ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рд╢рд╛рдпрдж NULL)ред рдПрдлрдПрд╕ рдЖрдорддреМрд░ рдкрд░ рд╕реНрдерд╛рдиреАрдп рд╕реНрдЯреНрд░реАрдо рд╕реНрдЯреЛрд░реЗрдЬ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рд╣реЛрдиреЗ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЬреАрдПрд╕ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рджреЛрд╣рд░рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЬреАрдПрд╕ рдЖрдорддреМрд░ рдкрд░ рдПрдХ рд╕реЗрдЧрдореЗрдВрдЯ рд╣реИ thread_infoред

 if (next->fs) wrmsrl(MSR_FS_BASE, next->fs); 

рдпрджрд┐ рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдореЗрдВ рдПрдлрдПрд╕ рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╕рдВрдкреВрд░реНрдг 64-рдмрд┐рдЯ рдорд╛рди рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рд╕реЗрдЧрдореЗрдВрдЯ рд░рдЬрд┐рд╕реНрдЯрд░ 16/32-рдмрд┐рдЯ рдпреБрдЧ рдХреА рдПрдХ рдХрд▓рд╛рдХреГрддрд┐ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢реЗрд╖ рдлрд╝рдВрдХреНрд╢рди рдпрд╣ рдЬрд╛рдВрдЪрддрд╛ рд╣реИ рдХрд┐ рдКрдкрд░реА 32 рдмрд┐рдЯреНрд╕ рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВред

 prev->fsindex = fsindex; 

рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП FS рд╕рд╣реЗрдЬреЗрдВред

 prev->userrsp = read_pda(oldrsp); write_pda(oldrsp, next->userrsp); write_pda(pcurrent, next_p); write_pda(kernelstack, (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); 

рдЖрдЧрд╛рдореА рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдкреАрдбреАрдП рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛, рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рдкреБрд░рд╛рдиреЗ рдЖрд░рдПрд╕рдкреА (рд╕рд┐рд╕реНрдХреЙрд▓) рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИред рдкреАрдбреАрдП рдХреЛ рд╕реНрдЯреНрд░реАрдо рдФрд░ рд╕реНрдЯреИрдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╕рд╛рде рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд▓рд┐рдирдХреНрд╕ 3.0: рдЖрдзреБрдирд┐рдХ рдУрдПрд╕ (2011)


рдирдВрдмрд░ рдХреЛ рдзреЛрдЦрд╛ рди рджреЗрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдВрд╕реНрдХрд░рдг 3.0 2.6.0 рдХреЗ рд▓рдЧрднрдЧ 8 рд╕рд╛рд▓ рдмрд╛рдж рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред рднрд╛рд░реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдПрдХ рдкреВрд░реА рдкреБрд╕реНрддрдХ рдХреЗ рдпреЛрдЧреНрдп рд╣реИрдВ, рдФрд░ рдореИрдВ рдЖрдкрдХреЛ рд╕рдм рдХреБрдЫ рдирд╣реАрдВ рдмрддрд╛ рд╕рдХрддрд╛ред рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, i386 рдФрд░ x86_64 рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдлрд╝рд╛рдЗрд▓реЛрдВ (process_32.c рдФрд░ process_64.sред) рдХреЗ рд╕рд╛рде x86 рдореЗрдВ рд╕рдВрдпреБрдХреНрдд рд╣реИрдВред рдпрд╣ рд▓реЗрдЦ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдмрдбрд╝рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдХреЗрд╡рд▓ рдмрд╛рдж рдореЗрдВ x86_64 рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗ ред рд╣рдо рдХреЗрд╡рд▓ рдХреБрдЫ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рд░реЗрдЦрд╛рдВрдХрд┐рдд рдХрд░реЗрдВрдЧреЗ рдФрд░ рдирд╡реАрдирддрдо рдПрд▓рдЯреАрдПрд╕ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВрдЧреЗред



рд▓рд┐рдирдХреНрд╕ 3.0.1 (рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдб x86_64)
 /** arch/x86/include/asm/system.h */ #define SAVE_CONTEXT "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t" #define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t" #define __EXTRA_CLOBBER \ ,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15" #define switch_to(prev, next, last) asm volatile(SAVE_CONTEXT "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ "call __switch_to\n\t" "movq "__percpu_arg([current_task])",%%rsi\n\t" __switch_canary "movq %P[thread_info](%%rsi),%%r8\n\t" "movq %%rax,%%rdi\n\t" "testl %[_tif_fork],%P[ti_flags](%%r8)\n\t" "jnz ret_from_fork\n\t" RESTORE_CONTEXT : "=a" (last) __switch_canary_oparam : [next] "S" (next), [prev] "D" (prev), [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), [ti_flags] "i" (offsetof(struct thread_info, flags)), [_tif_fork] "i" (_TIF_FORK), [thread_info] "i" (offsetof(struct task_struct, stack)), [current_task] "m" (current_task) __switch_canary_iparam : "memory", "cc" __EXTRA_CLOBBER) 

рдЖрда рд╕рд╛рд▓ - рдФрд░ рдореИрдХреНрд░реЛ рдореЗрдВ switch_to()рдХреЗрд╡рд▓ рдЪрд╛рд░ рдкрд░рд┐рд╡рд░реНрддрдиред рдЙрдирдореЗрдВ рд╕реЗ рджреЛ рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝реЗ рд╣реБрдП рд╣реИрдВ, рдФрд░ рдХреБрдЫ рднреА рдирдпрд╛ рдирд╣реАрдВ рд╣реИред

 movq "__percpu_arg([current_task])",%%rsi\n\t 

task_structрдЖрд░рдПрд╕рдЖрдИ рдХреЗ рд▓рд┐рдП рдирдП рдЯрд╛рдВрдХреЗ рдЪрд▓рддрд╛ рд╣реИ ред рдпрд╣ рдХрд╛рд░реНрдп рдЬрд╛рдирдХрд╛рд░реА рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХрд╛ "рдирдпрд╛" рддрд░реАрдХрд╛ рд╣реИ: рдкреНрд░рддреНрдпреЗрдХ рд╕реАрдкреАрдпреВ рдореЗрдВ рдПрдХ рд╕реНрдерд┐рд░ рдкреНрд░рддреАрдХ рд╣реЛрддрд╛ рд╣реИред рдкрд╣рд▓реЗ, рдЬрд╛рдирдХрд╛рд░реА GS: [рдкреАрдбреАрдП рдСрдлрд╕реЗрдЯ] рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрд▓рдмреНрдз рдереАред рдЗрд╕рдХреЗ рдмрд╛рдж рдХреЗ RSI рдСрдкрд░реЗрд╢рди рд╕рдВрд╕реНрдХрд░рдг 2.6 рдореЗрдВ рд╣реА рд╣реИрдВред

 __switch_canary 

рдпрд╣ рдореИрдХреНрд░реЛ рдЖрдкрдХреЛ рдЕрддрд┐рд░рд┐рдХреНрдд рд░реВрдк рд╕реЗ рдЬрд╛рдБрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ CONFIG_CC_STACKPROTECTOR рдореИрдХреНрд░реЛ рдХрд░реНрдиреЗрд▓ рдЕрд╕реЗрдВрдмрд▓реА рдХреЗ рджреМрд░рд╛рди рд╕рдХреНрд╖рдо рд╣реИ рдпрд╛ рдирд╣реАрдВред рдореИрдВ рдЗрд╕ рд╡рд┐рд╖рдп рдХреЛ рдмрд╣реБрдд рдЧрд╣рд░рд╛рдИ рд╕реЗ рдЦреЛрджрдиреЗ рд╡рд╛рд▓рд╛ рдирд╣реАрдВ рд╣реВрдВ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рдпрд╣ рддрдВрддреНрд░ рдвреЗрд░ рдХреЗ рд╣реИрдХрд░ рд╡рд┐рдирд╛рд╢ рд╕реЗ рдмрдЪрд╛рддрд╛ рд╣реИ ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдо рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдореВрд▓реНрдп рдХреЛ рдмрдЪрд╛рддреЗ рд╣реИрдВ, рдФрд░ рдмрд╛рдж рдореЗрдВ рд╣рдо рдЗрд╕реЗ рдЬрд╛рдВрдЪрддреЗ рд╣реИрдВред рдпрджрд┐ рдЕрд░реНрде рдмрджрд▓ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдкрд░реЗрд╢рд╛рдиреАред

 testl %[_tif_fork],%P[ti_flags](%%r8)\n\t jnz ret_from_fork\n\t 

рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХреНрд▓реЛрдирд┐рдВрдЧ / рдХрд╛рдВрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдирдпрд╛ рдХрд╛рд░реНрдп рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдлрд┐рд░ рдЖрдЧреЗ рдмрдврд╝рддрд╛ рд╣реИ ret_from_fork()ред рдпрд╣ рдПрдХ рдирд┐рд░реНрджреЗрд╢ рд╣реБрдЖ рдХрд░рддрд╛ рдерд╛ btr, рд▓реЗрдХрд┐рди рдЕрдм рд╣рдо рдХреЙрд▓ рд╕рдорд╛рдкреНрдд рд╣реЛрдиреЗ рддрдХ рдмрд┐рдЯ рдХреЗ рд░реАрд╕реЗрдЯ рдХреЛ рд╕реНрдердЧрд┐рдд рдХрд░ рджреЗрддреЗ рд╣реИрдВред рдкрд░реАрдХреНрд╖рдг рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдХрд╛рд░рдг рдирд╛рдо рдмрджрд▓рдХрд░ рдЬреЗрдПрдирдЬреЗрдб рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рдпрджрд┐ рдмрд┐рдЯ рд╕реЗрдЯ рд╣реИ, рддреЛ рдЯреЗрд╕реНрдЯ (рдФрд░) рд╕рдХрд╛рд░рд╛рддреНрдордХ рд╣реЛрдЧрд╛ред

 __switch_canary_oparam 

рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдХ рдХреИрдирд░реА рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ CONFIG_CC_STACKPROTECTORред

 __switch_canary_iparam 

рд▓рд┐рдирдХреНрд╕ 3.0.1 рдХреЗ рд▓рд┐рдП рдЗрдирдкреБрдЯ рд╕реНрдЯреИрдХ рдХреИрдирд░реА CONFIG_CC_STACKPROTECTOR

(x86_64 C)
 /** arch/x86/kernel/process_64.c */ __notrace_funcgraph struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread; struct thread_struct *next = &next_p->thread; int cpu = smp_processor_id(); struct tss_struct *tss = &per_cpu(init_tss, cpu); unsigned fsindex, gsindex; bool preload_fpu; preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5; /* we're going to use this soon, after a few expensive things */ if (preload_fpu) prefetch(next->fpu.state); /* Reload esp0, LDT and the page table pointer: */ load_sp0(tss, next); savesegment(es, prev->es); if (unlikely(next->es | prev->es)) loadsegment(es, next->es); savesegment(ds, prev->ds); if (unlikely(next->ds | prev->ds)) loadsegment(ds, next->ds); savesegment(fs, fsindex); savesegment(gs, gsindex); load_TLS(next, cpu); __unlazy_fpu(prev_p); /* Make sure cpu is ready for new context */ if (preload_fpu) clts(); arch_end_context_switch(next_p); /* Switch FS and GS. */ if (unlikely(fsindex | next->fsindex | prev->fs)) { loadsegment(fs, next->fsindex); if (fsindex) prev->fs = 0; } /* when next process has a 64bit base use it */ if (next->fs) wrmsrl(MSR_FS_BASE, next->fs); prev->fsindex = fsindex; if (unlikely(gsindex | next->gsindex | prev->gs)) { load_gs_index(next->gsindex); if (gsindex) prev->gs = 0; } if (next->gs) wrmsrl(MSR_KERNEL_GS_BASE, next->gs); prev->gsindex = gsindex; /* Switch the PDA and FPU contexts. */ prev->usersp = percpu_read(old_rsp); percpu_write(old_rsp, next->usersp); percpu_write(current_task, next_p); percpu_write(kernel_stack, (unsigned long)task_stack_page(next_p) + THREAD_SIZE - KERNEL_STACK_OFFSET); /* Now maybe reload the debug registers and handle I/O bitmaps */ if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT || task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) __switch_to_xtra(prev_p, next_p, tss); /* Preload the FPU context - task is likely to be using it. */ if (preload_fpu) __math_state_restore(); return prev_p; } 

рд╕реА рдХреЛрдб рдореЗрдВ рдХреБрдЫ рдмрджрд▓рд╛рд╡ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡реЗ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдХрдо рд╣реИрдВ, рд░рд┐рд▓реАрдЬ рдХреЗ рдмреАрдЪ рдЖрда рд╕рд╛рд▓ рджрд┐рдП рдЧрдП рд╣реИрдВред рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдХреЙрд╕реНрдореЗрдЯрд┐рдХ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рднреА рдШреЛрд╖рдгрд╛рдУрдВ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдЬрд╛рдирд╛ред рдпрд╣рд╛рдБ рдХреНрдпрд╛ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ:

 __notrace_funcgraph struct task_struct * __switch_to(...) 

рдПрдХ рдирдпрд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ __notrace_funcgraphрдЯреНрд░реИрдХрд┐рдВрдЧ рд╕реЗ рд╕рдХреНрд░рд┐рдп рдлреБрдЯ рдХреЛ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░рддрд╛ рд╣реИ switch_toред

 preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5; if (preload_fpu) prefetch(next->fpu.state); 

рдпрд╣ рдЬрд╛рдВрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдПрдлрдкреАрдпреВ рдЕрдВрддрд┐рдо рдХрд╛рд░реНрдп рдореЗрдВ рдкрд┐рдЫрд▓реЗ 5 рдмрд╛рд░ рд╕реНрд▓рд╛рдЗрд╕ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдлрд┐рд░ рдмрд╛рдж рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХреЛ рдХреИрд╢ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИред

 load_sp0(tss, next); 

рдХрд░реНрдиреЗрд▓ рд╕реНрдкреЗрд╕ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ, рдкреЗрдЬ рдЯреЗрдмрд▓ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рд╛рдЗрдкрд░рд╡рд┐рдЬрд░ (рдпрджрд┐ рд▓рд╛рдЧреВ рд╣реЛ) рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИред

 savesegment(es, prev->es); 

ES рдЦрдВрдб рдмрдЪрд╛рддрд╛ рд╣реИред рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдПрдХ рдирд╡реАрдирддрд╛ рдирд╣реАрдВ рд╣реИ, рд╕рд┐рд░реНрдл 2.6 рд╕реЗ рдЗрдирд▓рд╛рдЗрди рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рд╣реИ:asm volatile("movl %%es,%0" : "=m" (prev->es)); ред

 if (preload_fpu) clts(); 

рдЕрдЧрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рддреЛ рддреБрд░рдВрдд FPU рдХреЛ рд░рд┐рдмреВрдЯ рдХрд░рддрд╛ рд╣реИред рдЖрд╡реЗрджрди clts()- рдПрдХ рд╣реА рд╡рд┐рдЪрд╛рд░ рд╣реИ рдХрд┐ рд╣рдо рд▓рд┐рдирдХреНрд╕ рдХреЗ рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рджреЗрдЦрд╛ рдерд╛: "cmpl %%ecx,%2\n\t jne 1f\n\t clts\n"ред

 jne 1f\n\t clts\n" arch_end_context_switch(next_p); 

рд╡рд░реНрдЪреБрдЕрд▓рд╛рдЗрдЬреЗрд╢рди рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИ ред рд╕рд╛рдорд╛рдиреНрдп рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ, рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ ред рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП рдЕрдВрддрд┐рдо рдХрд░реНрдиреЗрд▓ рд╕рдВрд╕реНрдХрд░рдг рджреЗрдЦреЗрдВред

 if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT || task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) __switch_to_xtra(prev_p, next_p, tss); 

рдкреНрд░рд╢рд╛рд╕рдирд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд▓рдЧреЗ рд╣реБрдП рд╣реИрдВ, рдЬрд┐рд╕реЗ рдкрд╣рд▓реЗ switch_toрдбрд┐рдмрдЧ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдФрд░ I / O рдмрд┐рдЯрдореИрдк рдорд╛рдкрджрдВрдбреЛрдВ рд╕рд╣рд┐рдд рдЕрдВрдд рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред рд╣рдо рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдб рд╕рдореАрдХреНрд╖рд╛ 4.14.67 рдореЗрдВ рдмрддрд╛рдПрдВрдЧреЗред

 if (preload_fpu) __math_state_restore(); 

рдЗрд╕рдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдБрдЪ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж FPU рдХреЛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рд╕рдлрд▓ рд╕рдВрдпреЛрдЬрди рдХреЗ рд╕рд╛рде, рдбреЗрдЯрд╛ рдкрд╣рд▓реЗ рд╕реЗ рдХрд┐рдП рдЧрдП рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЪрдпрди рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреИрд╢ рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рд▓рд┐рдирдХреНрд╕ 4.14.67: рдирд╡реАрдирддрдо LTS (2018)


рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рдЖрдВрддрд░рд┐рдХ рдХрд╛рдордХрд╛рдЬ рдореЗрдВ рдпрд╣ рд╣рдорд╛рд░реА рд╕рдмрд╕реЗ рдЧрд╣рд░реА рд╡рд┐рд╕рд░реНрдЬрди рд╣реИред 3.0 рдХреА рд░рд┐рд╣рд╛рдИ рдХреЗ рдмрд╛рдж рд╕реЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХрд╛рдлреА рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдХреЛрдб рдХрд╛ рдЖрдпреЛрдЬрди рдХрд┐рдпрд╛ред рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рдпрд╣ рдЕрдм рд╕рд╛рдл рджрд┐рдЦрддрд╛ рд╣реИ рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рдХрд╣реАрдВ рдЬреНрдпрд╛рджрд╛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рд╣реИред X86_64 рдХреЗ рд▓рд┐рдП:




Linux 4.14.67
 /** arch/x86/include/asm/switch_to.h */ #define switch_to(prev, next, last) do { prepare_switch_to(prev, next); ((last) = __switch_to_asm((prev), (next))); } while (0) 

рдпрд╣ рдкреБрд░рд╛рдиреА рдЧреБрдард▓реА рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╕рд░рд▓ рджрд┐рдЦрддрд╛ рд╣реИред рдпрд╣ рдкреБрдирд░реНрдЧрдарди рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдерд╛ рдЬрдм рдПрдВрдбреА рд▓реБрддреЛрдорд┐рд░рд╕реНрдХреА рдиреЗ рд▓рдЧрднрдЧ рдорд┐рд▓рд╛рди рдХрд░реНрдиреЗрд▓ рд╕реНрдЯреИрдХ рдкреЗрд╢ рдХрд┐рдпрд╛ ред

 prepare_switch_to(prev, next); 

рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╕рдВрджрд░реНрднреЛрдВ рдХреЛ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХрд░реНрдиреЗрд▓ рд╕реНрдЯреИрдХ рдЙрдкрд▓рдмреНрдз рд╣реИрдВред рд╡рд╕реНрддреБрддрдГ рдореИрдк рдХрд┐рдП рдЧрдП рдХрд░реНрдиреЗрд▓ рд╕реНрдЯреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рд╕рдВрджрд░реНрдн рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рджреМрд░рд╛рди рдпрд╣ рд╕рдВрднрд╡ рджреЛрд╣рд░реА рддреНрд░реБрдЯрд┐ рдпрд╛ рдХрд░реНрдиреЗрд▓ рдЖрддрдВрдХ рд╕реЗ рдмрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИред

 ((last) = __switch_to_asm((prev), (next))); 

рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИред

рдПрдХ prepare_switch_toрд╣реА рд╕реНрд░реЛрдд рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ ред

рд▓рд┐рдирдХреНрд╕ 4.14.67
 /** arch/x86/include/asm/switch_to.h */ static inline void prepare_switch_to(struct task_struct *prev, struct task_struct *next) { #ifdef CONFIG_VMAP_STACK READ_ONCE(*(unsigned char *)next->thread.sp); #endif } 


 #ifdef CONFIG_VMAP_STACK 

рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рд╕реНрдЯреИрдХ рд╡рд░реНрдЪреБрдЕрд▓ рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рд╣рдореЗрдВ рдХреЗрд╡рд▓ рд╡рд░реНрдЪреБрдЕрд▓ рд╕реНрдЯреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдкрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдХрд░реНрдиреЗрд▓ рдмрд┐рд▓реНрдб рдХреЗ рджреМрд░рд╛рди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИред рдХрдИ рдЖрдзреБрдирд┐рдХ рд╡рд┐рддрд░рдгреЛрдВ рдореЗрдВ, рдЗрд╕рдХрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореВрд▓реНрдп рд╣реИ yesред

 READ_ONCE(*(unsigned char *)next->thread.sp); 

рдкреГрд╖реНрда рддрд╛рд▓рд┐рдХрд╛рдУрдВ (pgd) рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЧрд▓реЗ рд╕реНрдЯреИрдХ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦред рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдПрдХ рдРрд╕реЗ рдкреЙрдЗрдВрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬреЛ рди рдХреЗрд╡рд▓ рдкреГрд╖реНрдареЛрдВ рдХреЗ рдмрд╛рд╣рд░ (рдкреГрд╖реНрда-рдмрд╛рд╣рд░) рд╣реИ, рдмрд▓реНрдХрд┐ vmalloc рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╡рд┐рд▓рдВрдмрд┐рдд рд▓реЛрдбрд┐рдВрдЧ рдХреЗ рдХрд╛рд░рдг рдЗрд╕ рдХрд╛рд░реНрдп рдХреА рд╕реНрдореГрддрд┐ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рднреА рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдЖрдк рд╕рдорд╕реНрдпрд╛ рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣рд▓ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдкреЙрдЗрдВрдЯрд░ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдФрд░ рдЕрдкреНрд░рд╛рдкреНрдпрддрд╛ рдХрд╛ рдорддрд▓рдм рдХрд░реНрдиреЗрд▓ рдкреИрдирд┐рдХ рд╣реИ ред

рд▓рд┐рдирдХреНрд╕ 4.16.67
 /** arch/x86/entry/entry_64.S */ ENTRY(__switch_to_asm) UNWIND_HINT_FUNC /* Save callee-saved registers */ pushq %rbp pushq %rbx pushq %r12 pushq %r13 pushq %r14 pushq %r15 /* switch stack */ movq %rsp, TASK_threadsp(%rdi) movq TASK_threadsp(%rsi), %rsp #ifdef CONFIG_CC_STACKPROTECTOR movq TASK_stack_canary(%rsi), %rbx movq %rbx, PER_CPU_VAR(irq_stack_union)+stack_canary_offset #endif #ifdef CONFIG_RETPOLINE FILL_RETURN_BUFFER %r12, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW #endif /* restore callee-saved registers */ popq %r15 popq %r14 popq %r13 popq %r12 popq %rbx popq %rbp jmp __switch_to END(__switch_to_asm) 

рдореЗрдВ entry_64.S рдХрд╛рдо рд╣реИ рдХрд┐ рд▓рд┐рдирдХреНрд╕ рдореЗрдВ рдкрд┐рдЫрд▓реЗ 25 рд╡рд░реНрд╖реЛрдВ рдХреЗ рдЗрдирд▓рд╛рдЗрди рдХреЛрдбрд╛рдВрддрд░рдХ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИред

 UNWIND_HINT_FUNC 

рдУрдмреНрдЬреЗрдХреНрдЯреВрд▓ рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рдЯреВрд▓ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЯреВрд▓рдЯрд┐рдкреНрд╕ рдмрдирд╛рддрд╛ рд╣реИ рдЬреЛ рдмрд╕ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддрд╛ рд╣реИред рдпрд╣ рд╡рд┐рд╢реЗрд╖ рдмрд┐рд▓реНрдб рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬреЛ рд╕рд╛рдорд╛рдиреНрдп рд╕реА рднрд╛рд╖рд╛ рдХреЙрд▓рд┐рдВрдЧ рд╕рдореНрдореЗрд▓рдиреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдРрд╕реЗ рд╕рдВрдХреЗрдд рд╕рдВрд╕реНрдХрд░рдг 4.6 рдореЗрдВ рдУрдЖрд░рд╕реА "рдХреЛрдб рдЕрдирдЗрдиреНрдбрд░" рдХреЗ рд╕рдлрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдХрд╛рд░рдг рд╣реИрдВ ред

 pushq %rbp, %rbx, %r12, %r13, %r14, %r15 

рд╣рдо рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЛ рдкреБрд░рд╛рдиреЗ рд╕реНрдЯреИрдХ рдореЗрдВ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВ , рдЬрд┐рд╕рд╕реЗ рд╣рдо рд╕реНрд╡рд┐рдЪ рдХрд░рддреЗ рд╣реИрдВред

 movq %rsp, TASK_threadsp(%rdi) movq TASK_threadsp(%rsi), %rsp 

рдореИрдВ рдкреБрд░рд╛рдиреЗ рдФрд░ рдирдП рдХрд╛рд░реНрдп рдХреЗ рдмреАрдЪ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░реНрд╕ рд╕реНрд╡реИрдк рдХрд░рддрд╛ рд╣реВрдВред рд╕реАрдзреЗ рдкрд░рд┐рд╡реЗрд╢ рд╡рд┐рдзрд╛рдирд╕рднрд╛ рд╕реЗ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди RDI рдФрд░ RSI рдЗрдирдкреБрдЯ рддрд░реНрдХ рд╣реЛрддреЗ рд╣реИрдВ task_struct *, рдкрд┐рдЫрд▓рд╛ рдФрд░ рдЕрдЧрд▓реЗ рд╕рдореНрдореЗрд▓рдиреЛрдВ рд╕рд┐рд╕реНрдЯрдо рд╡реА ABI рдХреЗ рдЕрдиреБрд╕рд╛рд░ред рдпрд╣рд╛рдБ рдЙрдирдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рд╛рде рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХрд╛ рдПрдХ рд╕рдмрд╕реЗрдЯ рд╣реИ:



 #ifdef CONFIG_CC_STACKPROTECTOR movq TASK_stack_canary(%rsi), %rbx movq %rbx, PER_CPU_VAR(irq_stack_union)+stack_canary_offset 

рдпрджрд┐ рд╕реНрдЯреИрдХ рд╕реБрд░рдХреНрд╖рд╛ рд╕рдХреНрд╖рдо рд╣реИ, рддреЛ рдЗрд╕ рдХрд╛рд░реНрдп рдХрд╛ рдХреИрдирд░реА рдорд╛рди рд╡рд░реНрддрдорд╛рди CPU рдХреЗ рдЗрдВрдЯрд░рдкреНрдЯ рд╕реНрдЯреИрдХ рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рд╕реНрдерд╛рди рдкрд░ рд▓реЗ рдЬрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕реНрдЯреИрдХ рд╕реБрд░рдХреНрд╖рд╛ рдЖрдорддреМрд░ рдкрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рд╕рдХреНрд╖рдо рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рд╣реЛрддрд╛ рд╣реИред

 #ifdef CONFIG_RETPOLINE FILL_RETURN_BUFFER %r12, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW 

рдпрд╣ рд╢рд╛рдЦрд╛ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА (рд╕реНрдкреЗрдХреНрдЯрд░ рднреЗрджреНрдпрддрд╛) рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рд╢реЛрд╖рдг рд╕реЗ рд╕реБрд░рдХреНрд╖рд╛ рд╣реИ ред рд╢реБрджреНрдз рд╕реНрд╡рд░ !

 popq %r15, %r14, %r13, %r12, %rbx, %rbp 

рд░рд┐рд╡рд░реНрд╕ рдХреНрд░рдо рдореЗрдВ рдирдП рд╕реНрдЯреИрдХ рд╕реЗ рд╕рднреА рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ : (r15, r14, r13, r12, rbx, rbp)

рд▓рд┐рдирдХреНрд╕ 4.16.67 ( рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕реНрд░реЛрдд )
 /** arch/x86/kernel/process_64.c */ __visible __notrace_funcgraph struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread; struct thread_struct *next = &next_p->thread; struct fpu *prev_fpu = &prev->fpu; struct fpu *next_fpu = &next->fpu; int cpu = smp_processor_id(); struct tss_struct *tss = &per_cpu(cpu_tss_rw, cpu); WARN_ON_ONCE(IS_ENABLED(CONFIG_DEBUG_ENTRY) && this_cpu_read(irq_count) != -1); switch_fpu_prepare(prev_fpu, cpu); save_fsgs(prev_p); load_TLS(next, cpu); arch_end_context_switch(next_p); savesegment(es, prev->es); if (unlikely(next->es | prev->es)) loadsegment(es, next->es); savesegment(ds, prev->ds); if (unlikely(next->ds | prev->ds)) loadsegment(ds, next->ds); load_seg_legacy(prev->fsindex, prev->fsbase, next->fsindex, next->fsbase, FS); load_seg_legacy(prev->gsindex, prev->gsbase, next->gsindex, next->gsbase, GS); switch_fpu_finish(next_fpu, cpu); /* Switch the PDA and FPU contexts. */ this_cpu_write(current_task, next_p); this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p)); /* Reload sp0. */ update_sp0(next_p); /* Now maybe reload the debug registers and handle I/O bitmaps */ if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT || task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) __switch_to_xtra(prev_p, next_p, tss); #ifdef CONFIG_XEN_PV if (unlikely(static_cpu_has(X86_FEATURE_XENPV) && prev->iopl != next->iopl)) xen_set_iopl_mask(next->iopl); #endif if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) { unsigned short ss_sel; savesegment(ss, ss_sel); if (ss_sel != __KERNEL_DS) loadsegment(ss, __KERNEL_DS); } /* Load the Intel cache allocation PQR MSR. */ intel_rdt_sched_in(); return prev_p; } 

рдХреЛрдб рдХрд╛ рдпрд╣ рдЖрдЦрд┐рд░реА рдмреНрд▓реЙрдХ рдЖрдкрдХреЛ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдореЗрдВ рдирд╡реАрдирддрдо рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ! рдпрджрд┐ рдЖрдкрдиреЗ рддреБрд░рдВрдд рдЗрд╕ рд╕реНрдерд╛рди рдкрд░ рд▓реЗрдЦ рдХреЛ рд╕реНрдХреНрд░реЙрд▓ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рдЪрд┐рдВрддрд╛ рди рдХрд░реЗрдВ - рдореИрдВ рдпрд╣рд╛рдВ (рдФрд░) рдЕрдзрд┐рдХ рд╕реЗ рдЕрдзрд┐рдХ рдмрд┐рдВрджреБрдУрдВ рдкрд░ рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд░реВрдВрдЧрд╛ред рдХреБрдЫ рдЕрдкрд╡рд╛рджреЛрдВ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ рдЬреЛ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдореЗрдВ рдЖрддреЗ рд╣реИрдВред

 __visible __notrace_funcgraph struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) 

C рдкрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рд▓рд┐рдП рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрдИ рднрд╛рдЧреЛрдВ рдореЗрдВ рд╣реИрдВ:

  • рдЕрджреГрд╢реНрдп - рдпрд╣ рд╡рд┐рд╢реЗрд╖рддрд╛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддреА рд╣реИ рдХрд┐ рд▓реЗрдЖрдЙрдЯ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рджреМрд░рд╛рди рдЕрдиреБрдХреВрд▓рди рдЪрд░рд┐рддреНрд░ рдХреЛ рдирд╣реАрдВ рд╣рдЯрд╛рддрд╛ рд╣реИ __switch_to()ред
  • __notrace_funcgraph - рдлреБрдЯреНрд░реЗрд╕__switch_to() рдЯреНрд░реЗрд╕рд░ рд╕реЗ рдмрдЪрд╛рддрд╛ рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрд╕реНрдХрд░рдг 2.6.29 рдореЗрдВ рд▓рдЧрднрдЧ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЬрд▓реНрдж рд╣реА рдЗрд╕реЗ рдЪрд╛рд▓реВ рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
  • рдЗрдирдкреБрдЯ рддрд░реНрдХ рдкреБрд░рд╛рдиреЗ рдФрд░ рдирдП рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рдВрдХреЗрдд рд╣реИрдВ рдЬреЛ RDI рдФрд░ RSI рдХреЛ рджрд┐рдП рдЧрдП рд╣реИрдВред

 struct thread_struct *prev = &prev_p->thread; struct thread_struct *next = &next_p->thread; struct fpu *prev_fpu = &prev->fpu; struct fpu *next_fpu = &next->fpu; 

рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рд╕реЗ рдХреБрдЫ рдЬрд╛рдирдХрд╛рд░реА рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИ task_struct *ред рдереНрд░реЗрдб_рд╕реНрдЯреНрд░реИрдХ рдореЗрдВ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП TSS рдбреЗрдЯрд╛ (рд░рдЬрд┐рд╕реНрдЯрд░ рдЖрджрд┐) fpu>рд╢рд╛рдорд┐рд▓ рд╣реИрдВ ред рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ FPU рдбреЗрдЯрд╛ рд╢рд╛рдорд┐рд▓ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдЕрдВрддрд┐рдо рд╕реАрдкреАрдпреВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЖрд░рдВрднреАрдХрд░рдг рдФрд░ рд░рдЬрд┐рд╕реНрдЯрд░ рдореВрд▓реНрдпред

 int cpu = smp_processor_id(); 

рдкреНрд░реЛрд╕реЗрд╕рд░ рдирдВрдмрд░ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдореЗрдВ TSS рдбреЗрдЯрд╛, рд╕реНрдерд╛рдиреАрдп рдереНрд░реЗрдб рд╕реНрдЯреЛрд░реЗрдЬ рдФрд░ рдЧреИрд╕ рдЬрдирд░реЗрдЯрд░ рдХреА рд╕реНрдерд┐рддрд┐ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП GDT рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

 struct tss_struct *tss = &per_cpu(cpu_tss_rw, cpu); 

рд╡рд░реНрддрдорд╛рди TSS CPU рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ ред

 WARN_ON_ONCE(IS_ENABLED(CONFIG_DEBUG_ENTRY) && this_cpu_read(irq_count) != -1); 

рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди IRQ рд╕реНрдЯреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВ рдФрд░ рдкреНрд░рддрд┐ рд▓реЛрдб рдПрдХ рдмрд╛рд░ рдЗрд╕рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рд╡рд┐рдХрд╛рд╕ 4.14 рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдХреЛрдб рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

 switch_fpu_prepare(prev_fpu, cpu); 

рдПрдлрдкреАрдпреВ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдЪрд╛рддрд╛ рд╣реИ рдЬрдмрдХрд┐ рд╣рдо рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдореЗрдВ рд╣реИрдВред

 save_fsgs(prev_p); 

рдПрдлрдПрд╕ рдФрд░ рдЬреАрдПрд╕ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣рдо рд╕реНрдерд╛рдиреАрдп рд╕реНрдЯреНрд░реАрдо рд╕реНрдЯреЛрд░реЗрдЬ рдХреЛ рдмрджрд▓рддреЗ рд╣реИрдВред

 load_TLS(next, cpu); 

рдирдП рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕реНрдерд╛рдиреАрдп рдереНрд░реЗрдб рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдЬреАрдбреАрдЯреА рдХреЛ рдкреБрдирдГ рд▓реЛрдб рдХрд░реЗрдВред рдпрд╛рдВрддреНрд░рд┐рдХ рд░реВрдк рд╕реЗ tls_array рдХреЛ рдПрдХ рдирдИ рд╕реНрдЯреНрд░реАрдо рд╕реЗ GDT рд░рд┐рдХреЙрд░реНрдб 6, 7, рдФрд░ 8 рдореЗрдВ рдХреЙрдкреА рдХрд░рддрд╛ рд╣реИред

 arch_end_context_switch(next_p); 

рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХреЗрд╡рд▓ paravirtualization рдХреЗ рд╕рд╛рде рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред Paravirt рдореЛрдб рдХреЛ рдмрджрд▓рддрд╛ рд╣реИ рдФрд░ рд╢реЗрд╖ рд╕рднреА рдмреИрдЪ рдХрд╛рд░реНрдп рдХреЛ рд╕рд╛рдлрд╝ рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓ рдХреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд 2.6.x. рдореИрдВ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдореЗрдВ рдмрд╣реБрдд рдордЬрдмреВрдд рдирд╣реАрдВ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рдЕрдиреБрд╕рдВрдзрд╛рди рдХреЗ рд▓рд┐рдП рдкрд╛рдардХреЛрдВ рдкрд░ рдЫреЛрдбрд╝ рджреВрдВрдЧрд╛ ред

 savesegment(es, prev->es); if (unlikely(next->es | prev->es)) loadsegment(es, next->es); 

ES рдЦрдВрдб рдмрдЪрд╛рддрд╛ рд╣реИ рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдПрдХ рдирдпрд╛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИред рдПрдХ рд╕рдорд╛рди рдбреАрдПрд╕ рдХреЙрд▓ рдЫреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рднрд▓реЗ рд╣реА рдирдпрд╛ рдХрд╛рд░реНрдп рдбреАрдПрд╕ / рдИрдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдлрд┐рд░ рднреА рдпрд╣ рд╕рднреА рдкреБрд░рд╛рдиреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рд╣рдЯрд╛ рджреЗрдЧрд╛ред

 load_seg_legacy(prev->fsindex, prev->fsbase, next->fsindex, next->fsbase, FS); 

рдирдП FS рд╕реЗрдЧрдореЗрдВрдЯреНрд╕ (GS рдЫреЛрдбрд╝рд╛ рдЧрдпрд╛)ред рдпрд╣ 32-рдмрд┐рдЯ рдФрд░ 64-рдмрд┐рдЯ рд░рдЬрд┐рд╕реНрдЯрд░ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдПрдЧрд╛ рдФрд░ рд▓реЛрдб рдХрд░реЗрдЧрд╛ред рдирдпрд╛ рдХрд╛рд░реНрдп рдЕрдм рдЯреАрдПрд▓рдПрд╕ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИред

 switch_fpu_finish(next_fpu, cpu); 

рдЖрдиреЗ рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП FPU рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЖрд░рдореНрдн рдХрд░рддрд╛ рд╣реИред

 this_cpu_write(current_task, next_p); 

рд╡рд░реНрддрдорд╛рди рд╕реАрдкреАрдпреВ ( task_struct *) рдХрд╛рд░реНрдп рдХреЛ рдЕрджреНрдпрддрди рдХрд░рддрд╛ рд╣реИ ред рдПрдлрдкреАрдпреВ рдФрд░ рдкреАрдбреАрдП (рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХреНрд╖реЗрддреНрд░) рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдкреНрд░рднрд╛рд╡реА рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИред

 this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p)); 

рд╕реАрдкреАрдпреВ рдвреЗрд░ рд╕реВрдЪрдХ рд╣реИ рдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЗ рд░реВрдк рдореЗрдВ SP1 рдУрд╡рд░рд▓реЛрдб рд╣реЛ рдЧрдпрд╛ рд╣реИ рдЕрджреНрдпрддрди рдХрд░рддрд╛ рд╣реИ рдЙрддреНрдкрдиреНрди рдХреЛрдб рдХреА рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП (рдкреНрд░рд╡реЗрд╢ рдЯреНрд░реИрдореНрдкреЛрд▓рд┐рди)ред

 update_sp0(next_p); 

рдЗрд╕реЗ рдЬрд╛рдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдП рд╕реНрдЯреИрдХ рдХрд╛ рд╕рддреНрдпрд╛рдкрдиред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ sp0 рдпрд╣рд╛рдБ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, sp1 рдирд╣реАрдВ? рд╢рд╛рдпрдж рдирд╛рдо рдмрджрд▓рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

 if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT || task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) __switch_to_xtra(prev_p, next_p, tss); 

рдЕрдкрдбреЗрдЯ рдбрд┐рдмрдЧ рд░рдЬрд┐рд╕реНрдЯрд░ рдФрд░ I / O рдмрд┐рдЯрдореИрдкреНрд╕ред рдЗрди рджреЛрдиреЛрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкрд╣рд▓реЗ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдореЗрдВ рд╕реАрдзреЗ рд╣реИрдВрдбрд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЕрдм рдЗрд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ __switch_to_xtra()ред

 #ifdef CONFIG_XEN_PV if (unlikely(static_cpu_has(X86_FEATURE_XENPV) && prev->iopl != next->iopl)) xen_set_iopl_mask(next->iopl); 

Xen paravirtualization рдХреЗ рд▓рд┐рдП I / O рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░ рдмрд┐рдЯреНрд╕ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕реНрд╡реИрдк рдХрд░рддрд╛ рд╣реИред рдЬрд╛рд╣рд┐рд░рд╛ рддреМрд░ рдкрд░, рдирд┐рдпрдорд┐рдд рдзреНрд╡рдЬ рд╕реНрд╡рд┐рдЪ рдареАрдХ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ , рдФрд░ рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рд╕реАрдзреЗ рд╡рд░реНрддрдорд╛рди рдмрд┐рдЯреНрд╕ рдХреЛ рдореБрдЦреМрдЯрд╛ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

 if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) { unsigned short ss_sel; savesegment(ss, ss_sel); if (ss_sel != __KERNEL_DS) loadsegment(ss, __KERNEL_DS); 

рдПрдПрдордбреА рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЗрдВ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд SYSRET рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдЫреБрдкрд╛рддрд╛ рд╣реИ рдЬреЛ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рд╕реЗрдЧрдореЗрдВрдЯ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИред

 intel_rdt_sched_in(); 

рдХреБрдЫ рдЗрдВрдЯреЗрд▓ рд╕рдлрд╛рдИ рдХрд╛рд░реНрдпред рдЕрдкрдбреЗрдЯ рдЖрд░рдПрдордЖрдИрдбреА рдФрд░ рдХреНрд▓реЛрд╕рд┐рдб ред

 return prev_p; 

рд╣реЛ рдЧрдпрд╛!

рдкреВрдЫреЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рд╢реНрди


рдЖрдкрдиреЗ рдЗрди рдХрд░реНрдиреЗрд▓ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЛ рдХреНрдпреЛрдВ рдЪреБрдирд╛?
рдкрд╣рд▓реЗ рдФрд░ рдЕрдВрддрд┐рдо рд╕рдВрд╕реНрдХрд░рдг рд╕реНрдкрд╖реНрдЯ рдЙрдореНрдореАрджрд╡рд╛рд░ рдереЗред рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдореИрдВрдиреЗ рдЪрд╛рд░ рдФрд░ рдордзреНрдпрд╡рд░реНрддреА рд╕рдВрд╕реНрдХрд░рдгреЛрдВ (2.1, 2.3, 2.5 рдФрд░ 2.6.26) рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ, рд▓реЗрдХрд┐рди рд▓реЗрдЦ рдХреЛ рдУрд╡рд░-рдЗрдирдлрд╝реНрд▓реЛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рд╡рд░реНрддрди рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рдереЗред рд╡рд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдмрдбрд╝реА рд╣реИред

рдЗрд╕ рдЕрдзреНрдпрдпрди рдореЗрдВ рдХрд┐рддрдирд╛ рд╕рдордп рд▓рдЧрд╛?
рджреЛ рд╕рдкреНрддрд╛рд╣ред рдХреЛрдб рд╡рд┐рд╢реНрд▓реЗрд╖рдг, рдиреЛрдЯреНрд╕ рдФрд░ рддрдХрдиреАрдХреА рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдкреНрддрд╛рд╣ред рдлрд┐рд░ рдиреЛрдЯреНрд╕ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ, рдЪрд┐рддреНрд░ рдмрдирд╛рдиреЗ рдФрд░ рд▓реЗрдЦ рдХреЛ рдкреНрд░рд╛рд░реВрдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдкреНрддрд╛рд╣ред

4.14.67 - рдирд╡реАрдирддрдо рдПрд▓рдЯреАрдПрд╕ рд░рд┐рд▓реАрдЬ рдирд╣реАрдВ?
рдореИрдВрдиреЗ 1 рд╕рд┐рддрдВрдмрд░ рдХреЛ рдХреЛрдб рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдФрд░ рд╕реНрд░реЛрдд рдХреЛрдб 4.14.67 рд▓рд┐рдпрд╛ред рд╕рдВрд╕реНрдХрд░рдг 4.14.68 рдХреЛ рдЪрд╛рд░ рджрд┐рди рдмрд╛рдж рдкреВрд░рд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдЬреИрд╕реЗ рд╣реА рд╡реЗ рдЙрдкрд▓рдмреНрдз рд╣реЛрдВрдЧреЗ рдореИрдВ рдЕрдиреНрдп рдкреНрд░рд╢реНрди рдЬреЛрдбрд╝ рджреВрдВрдЧрд╛ред

Source: https://habr.com/ru/post/hi438042/


All Articles