
рдкрд┐рдЫрд▓реЗ рд╕рдкреНрддрд╛рд╣рд╛рдВрдд рдореЗрдВ, 80386 рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдк рддрдереНрдпреЛрдВ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рддреЗ рд╣реБрдП, рдореБрдЭреЗ рдЕрдЪрд╛рдирдХ рдпрд╛рдж рдЖрдпрд╛ рдХрд┐ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдХреЗ рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдереЗред рдФрд░ рдореИрдВ рдЙрд╕ рдХреЛрдб рдореЗрдВ рдбреВрдм рдЧрдпрд╛ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдХрдИ рд╕рд╛рд▓реЛрдВ рд╕реЗ рдирд╣реАрдВ рджреЗрдЦрд╛ рдерд╛ред рдЕрдм рдореИрдВрдиреЗ рд▓рд┐рдирдХреНрд╕ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕ рдЕрджреНрднреБрдд рдпрд╛рддреНрд░рд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред рдореИрдВ рд╕рднреА рд╕реЛрдиреЗ рдХреА рдбрд▓реА рдФрд░ рдордЬреЗрджрд╛рд░ рдХрд▓рд╛рдХреГрддрд┐рдпреЛрдВ рдХреЛ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдЬреЛ рдореБрдЭреЗ рд░рд╛рд╕реНрддреЗ рдореЗрдВ рдорд┐рд▓реАрдВред
рдЙрджреНрджреЗрд╢реНрдп: рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЛ рдкрд╣рд▓реЗ (0.01) рд╕реЗ рдмрджрд▓рдХрд░ LTS (4.14.67) рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХреИрд╕реЗ рдЯреНрд░реИрдХ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдкрд╣рд▓реЗ рдФрд░ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдкрд░ рд╡рд┐рд╢реЗрд╖ рдЬреЛрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдХрд╣рд╛рдиреА рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рд╕рдВрджрд░реНрднреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХ рдЫреЛрдЯреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЖрдзреБрдирд┐рдХ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рд▓рд┐рдирдХреНрд╕ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИред рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдмрд╕ рдЗрд╕ рдХрд╣рд╛рдиреА рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред
рд╣рдо рдХрд┐рд╕ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ?
рдпрджреНрдпрдкрд┐ рдХрдИ рдЪреАрдЬреЗрдВ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд░реНрдиреЗрд▓ рдореЛрдб рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдирд╛, рдПрдХ рдмрд╛рдзрд╛ рд╣реИрдВрдбрд▓рд░ рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдирд╛), рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдЖрдорддреМрд░ рдкрд░ рд╕реНрд╡реАрдХреГрдд рдЕрд░реНрде:
рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рдмреАрдЪ рд╕реНрд╡рд┐рдЪ рдХрд░рдирд╛ ред рд▓рд┐рдирдХреНрд╕ рдкрд░, рдпрд╣
switch_to()
рдореИрдХреНрд░реЛ рдФрд░ рдЗрд╕рдореЗрдВ рд╕рдм рдХреБрдЫ рд╣реИред
рдпрд╣ рдореИрдХреНрд░реЛ рджреЛ рдФрд░ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рд╕рд░рд▓ рдпрд╛рдВрддреНрд░рд┐рдХ рдХреНрд░рд┐рдпрд╛ рд╣реИ: рдПрдХ рдХрд╛рд░реНрдп рдЕрдиреБрд╕реВрдЪрдХ рдФрд░ рдПрдХ рд╕реАрдкреАрдпреВред рдУрдПрд╕ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдореЗрдВ рдХрд╛рд░реНрдп рдпреЛрдЬрдирд╛ рд░рдгрдиреАрддрд┐рдпреЛрдВ рдХреЛ рдорд┐рд▓рд╛рдиреЗ рдФрд░ рд╕рдордиреНрд╡рдп рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реЛрддреА рд╣реИред рд╕реАрдкреАрдпреВ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рднреА рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЦреБрд▓реЗ рд╣реИрдВ: рд▓рд┐рдирдХреНрд╕ рджрд░реНрдЬрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдЙрдирдХреЗ рдмреАрдЪ рдХрд╛ рдЧрд┐рдпрд░ рд╣реИред рдЗрд╕рдХрд╛ "рдбрд┐рдЬрд╝рд╛рдЗрди" рдЗрд╕рдХреЗ рдкрдбрд╝реЛрд╕рд┐рдпреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдУрдПрд╕ рдХрд╛
рдХрдо рд╕реЗ
рдХрдо рджрд┐рд▓рдЪрд╕реНрдк рд╣рд┐рд╕реНрд╕рд╛ рд╣реЛрдиреЗ рдХрд╛ рджрд╛рд╡рд╛ рдХрд░рддрд╛ рд╣реИред рдореИрдВ рджреЛрд╣рд░рд╛рддрд╛ рд╣реВрдВ: рд╡рд╣ рд╡рд╣реА рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред
рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдПрдХ рдЫреЛрдЯреА рд╕реВрдЪреА:
- рдХрд╛рд░реНрдпрдХреНрд╖реЗрддреНрд░ рдУрд╡рд░рд░рд╛рдЗрдб: рд╕реНрдЯреИрдХ рд░рд┐рдХрд╡рд░реА (рдПрд╕рдПрд╕: рдПрд╕рдкреА)ред
- рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рд░реНрджреЗрд╢ рдЦреЛрдЬреЗрдВ: IP рд░рд┐рдХрд╡рд░реА (CS: IP)ред
- рдЯрд╛рд╕реНрдХ рд╕реНрдЯреЗрдЯ рд░рд┐рдХрд╡рд░реА: рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдпреЛрдЬрди рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреА рдмрд╣рд╛рд▓реАред
- рдореЗрдореЛрд░реА рдПрдбреНрд░реЗрд╕ рд╕реНрдкреЗрд╕ рд╕реНрд╡реИрдк рдХрд░рдирд╛: рдкреЗрдЬ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА (CR3) рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛
- ... рдФрд░ рдмрд╣реБрдд рдХреБрдЫ: рдПрдлрдкреАрдпреВ, рдУрдПрд╕ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВ, рдбрд┐рдмрдЧ рд░рдЬрд┐рд╕реНрдЯрд░, рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб, рдЖрджрд┐ред
рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрдм рдФрд░ рдХрд╣рд╛рдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрджрд┐ рд╕реАрдкреАрдпреВ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд▓реЗрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд▓рд┐рдирдХреНрд╕ 2.2 рд╕реЗ рдкрд╣рд▓реЗ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХрд╛рд░реНрдп 2, 3 рдХреЛ рдЫреБрдкрд╛рддрд╛ рд╣реИ, рдФрд░ 4. рдХрд░реНрдиреЗрд▓ рдореЛрдб рдХреЗ рдмреАрдЪ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╕реЗ рдЯрд╛рд╕реНрдХ 3 рд╕реАрдорд┐рдд рд╣реИред рд╢реЗрдбреНрдпреВрд▓рд░ рд░рд┐рдЯрд░реНрди рдХреЗ рдмрд╛рдж рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдереНрд░реЗрдб рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рдПрдХ
iret
рдХрд╛рд░реНрдп рд╣реИред рд╡рд┐рднрд┐рдиреНрди рдХрд░реНрдиреЗрд▓ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рдЗрдирдореЗрдВ рд╕реЗ рдХрдИ рдХрд╛рд░реНрдп
switch_to()
рдФрд░ рдЕрдиреБрд╕реВрдЪрдХ рдХреЗ рдмреАрдЪ
switch_to()
ред рд╣рдо рдХреЗрд╡рд▓ рдЧрд╛рд░рдВрдЯреА рджреЗ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рд╣рдо рд╣рдореЗрд╢рд╛ рдПрдХ рд╕реНрдЯреИрдХ рд╕реНрд╡реИрдк рдФрд░ рдПрдлрдкреАрдпреВ рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рджреЗрдЦреЗрдВрдЧреЗред
рдпрд╣ рдХрд┐рд╕рдХреЗ рд▓рд┐рдП рд╣реИ?
рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдирд╣реАрдВред рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХреЗрд╡рд▓ x86 рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЛ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдФрд░, рд╕рдВрднрд╡рддрдГ, OS рдбрд┐рдЬрд╝рд╛рдЗрди рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдиреНрдпреВрдирддрдо рд╢рд┐рдХреНрд╖рд╛ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
рдореБрдЭреЗ
рддреБрд░рдВрдд рдпрд╣ рдХрд╣рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдореИрдВ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдХрд╛
рдЕрдиреБрд░рдХреНрд╖рдХ рдпрд╛ рдпреЛрдЧрджрд╛рдирдХрд░реНрддрд╛ рдирд╣реАрдВ рд╣реВрдВред рдЗрди рдХрд╛рдорд░реЗрдбреЛрдВ рд╕реЗ рдпрд╛
рдХрд░реНрдиреЗрд▓ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдореЗрд▓рд┐рдВрдЧ рд╕реВрдЪреА рд╕реЗ рдХреЛрдИ рднреА рдЬрд╛рдирдХрд╛рд░реА рдЬреЛ рдореЗрд░реА рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╡рд┐рдкрд░реАрдд рд╣реИ, рдХреЛ рдЧрдВрднреАрд░рддрд╛ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИ, рди рдХрд┐ рдПрдХ рд╕рд╣рдХрд░реНрдореА рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХреА рдЧрдИ рдкрддреНрд░рд┐рдХрд╛ рдореЗрдВ рдПрдХ рд╡реИрдЬреНрдЮрд╛рдирд┐рдХ рд▓реЗрдЦред
1.0 рд╕реЗ рдкрд╣рд▓реЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд▓рд┐рдирдХреНрд╕: рдкреНрд░рд╛рдЪреАрди рдЗрддрд┐рд╣рд╛рд╕ (1991)
рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рд╕рд░рд▓ рдФрд░ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рдореБрдЦ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреА рдПрдХ рдЫреЛрдЯреА рд╕реВрдЪреА рд╣реИ:
- рдПрдХрд▓ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ (80386 / i386): рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪред рдХрдИ 80386 рд╕реБрд╡рд┐рдзрд╛рдПрдБ рдкреВрд░реЗ рдХреЛрд░ рдореЗрдВ рд╣рд╛рд░реНрдбрдХреЛрдб рдХреА рдЧрдИ рд╣реИрдВред рдЗрди рднрд╛рдЧреЛрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЗрдВрдЯреЗрд▓ 80386 рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдЧрд╛рдЗрдб (1986) рд▓рд┐рдпрд╛ред
- рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ: рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрд░реНрдиреЗрд▓ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рддрдВрддреНрд░ 80386 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
- рдкреНрд░реАрдореЗрдкреНрдЯрд┐рд╡ рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛: рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рдХреЗрд╡рд▓ рдПрдХ рд╕реАрдкреАрдпреВ рд╕рдХреНрд░рд┐рдп рд╣реЛрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдФрд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд┐рд╕реА рднреА рд╕рдордп рд╢реБрд░реВ рд╣реЛ рд╕рдХрддреА рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╕рд╛рдорд╛рдиреНрдп рддреБрд▓реНрдпрдХрд╛рд▓рди рдирд┐рдпрдо рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ: рд╕рд╛рдЭрд╛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд░рдирд╛ (рд╕реНрдкрд┐рди-рд▓реЙрдХ рдХреЗ рдмрд┐рдирд╛)ред рдПрдХ рдЪрд░рдо рдорд╛рдорд▓реЗ рдореЗрдВ, рдЗрдВрдЯрд░рдкреНрдЯ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ рд▓реЙрдХ рдХрд░рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред

рдЖрдЧреЗ рдХреА рд╣рд▓рдЪрд▓ рдХреЗ рдмрд┐рдирд╛, рджреЛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдХреЛрдб рдХреЛ рдмреЗрд╣рддрд░ рдкрдардиреАрдпрддрд╛ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рд░реВрдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рдирд┐рд░рдВрддрд░рддрд╛ рд╡рд░реНрдгреЛрдВ (\) рдХреЗ рдмрд┐рдирд╛ рдкреНрд░рддрд┐ рдкрдВрдХреНрддрд┐ рдПрдХ рддрддреНрд╡ред
рд▓рд┐рдирдХреНрд╕ 0.01 #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 #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-рдмрд┐рдЯ рдЦрдВрдб рдЪрдпрдирдХрд░реНрддрд╛ |
---|
0 | 0000000000100 0 00 |
1 | 0000000000110 0 00 |
2 | 0000000001000 0 00 |
3 | 0000000001010 0 00 |
4 | 0000000001100 0 00 |
5 | 0000000001110 0 00 |
6 | 0000000010000 0 00 |
7 | 0000000010010 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 #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:" : :"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 рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╕рдм рдХреБрдЫ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реИред рдЯреАрдПрд╕ рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкрд┐рдЫрд▓реЗ рдХрд╛рд░реНрдп рд╕реЗ рдЧрдгрд┐рддреАрдп рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд╕рдорд╛рд╢реЛрдзрди рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддрд╛ рд╣реИред
:
рдЗрд╕ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ рдХрд╛ рдХреЛрдИ рдЖрдЙрдЯрдкреБрдЯ рдирд╣реАрдВ рд╣реИ - рдХрд░реНрдиреЗрд▓ рдХреЗ рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреА рдХрдореА рд╕реЗ рдХреЛрдИ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд╛рд░рд╛рдЬ рдерд╛ред
:"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 #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:" : :"m" (*(((char *)&tsk->tss.tr)-4)), "c" (tsk) :"cx"); 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);
__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:" : :"m" (*(((char *)&tsk->tss.tr)-4)), "c" (tsk) :"cx");
рд▓рд┐рдирдХреНрд╕ 1.0 рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХреЛрдИ рдкрд░рд┐рд╡рд░реНрддрди рдирд╣реАрдВред рдлрд┐рд░ рднреА, рдЗрдВрдЯрд░рдкреНрдЯ рдХреЛ рдХрд░рдВрдЯ рд╕реЗ * task_struct рд╕реНрд╡реИрдк рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдХреНрд╖рдо рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдлрд┐рд░ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХреЛрдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЪреЗрдХ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
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 (рдпреВрдкреА) #else #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:" : :"m" (*(((char *)&next->tss.tr)-4)), "r" (prev), "r" (next)); 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:" : :"m" (*(((char *)&next->tss.tr)-4)),
рдХреЛрдИ рдмрджрд▓рд╛рд╡ рдирд╣реАрдВ рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣рдордиреЗ рдмрд╛рдд рдирд╣реАрдВ рдХреА рд╣реИред "r" (prev), "r" (next));
рдЕрдм рд╣рдо рдЗрдирд▓рд╛рдЗрди рдЕрд╕реЗрдВрдмрд▓рд░ рдХреЗ рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рджреЛрдиреЛрдВ рдХрд╛рд░реНрдп рдХрд░рддреЗ рд╣реИрдВред рдПрдХ рдорд╛рдореВрд▓реА рдмрджрд▓рд╛рд╡ рдпрд╣ рд╣реИ рдХрд┐ рдЕрдм рд░рдЬрд┐рд╕реНрдЯрд░ рдХреЗ рдХрд┐рд╕реА рднреА рдЙрдкрдпреЛрдЧ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред рдпрд╣ рдкрд╣рд▓реЗ next
ECX рдореЗрдВ рдПрдирдХреЛрдбреЗрдб рдерд╛ред 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 (рдПрд╕рдПрдордкреА) #ifdef __SMP__ #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" : :"m" (*(((char *)&next->tss.tr)-4)), "c" (next)); 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_reg
OS рдЖрд░рдВрднреАрдХрд░рдг рдХреЗ рджреМрд░рд╛рди рдкреНрд░рд╕рд╛рд░рдгред "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 рдХреЛрдб
(рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ) рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ #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" "movl %5,%%esp\n\t" "movl $1f,%1\n\t" "pushl %6\n\t" "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" "movl %5,%%esp\n\t"
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдкреБрд░рд╛рдиреА рдФрд░ рдирдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдмреАрдЪ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░реНрд╕ рд╕реНрд╡реИрдк рдХрд░рддреЗ рд╣реИрдВред рдкреБрд░рд╛рдиреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдСрдкрд░реЗрдВрдб% 0 ( prev->tss.esp
) рд╣реИ, рдЬрдмрдХрд┐ рдирдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ % 5 ( next->tss.esp
) рд╣реИред "movl $1f,%1\n\t"
рд╕рдВрджрд░реНрдн рд╡рд╛рдкрд╕ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ рдЕрдЧрд▓реЗ рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢ рд╕реВрдЪрдХ рдХреЗ рдореВрд▓реНрдп рдХреЛ рд╕рд╣реЗрдЬрдирд╛ред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдирд┐рдореНрди рдХрдерди рдХрд╛ рдорд╛рди рдПрдХ рд▓реЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ 1
: "pushl %6\n\t"
рдирдП рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рд░реНрджреЗрд╢ рддреИрдпрд╛рд░ рдХрд░реЗрдВред рдЪреВрдВрдХрд┐ рд╣рдордиреЗ рдЕрднреА рдПрдХ рдирдП рд╕реНрдЯреИрдХ рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЖрдИрдкреА рдирдП рдХрд╛рд░реНрдп рдХреЗ TSS рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рд╕реНрдЯреИрдХ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред рдирд┐рд╖реНрдкрд╛рджрди рд╕реА тАЛтАЛрдХреЛрдб рдХреЗ 'рд░рд┐рдЯ' рдХреЗ рдмрд╛рдж рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдерди рд╕реЗ рд╢реБрд░реВ рд╣реЛрдЧрд╛ рдЬрд┐рд╕реЗ рд╣рдо рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВред "jmp __switch_to\n"
рд╣рдо рдЕрдкрдиреЗ рдирдП рдФрд░ рдмреЗрд╣рддрд░ рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ (рдиреАрдЪреЗ рджреЗрдЦреЗрдВ)ред "popl %%ebp\n\t" "popl %%edi\n\t" "popl %%esi\n\t" "popl %%ebx"
рд╣рдо рдПрдХ рдирдП рд╕рдордп рдЕрдВрддрд░рд╛рд▓ рдореЗрдВ рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕рдВрднрд╡рддрдГ рд░рд┐рд╡рд░реНрд╕ рдСрд░реНрдбрд░ рдореЗрдВ рд╕реНрдЯреИрдХ рд╕реЗ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВредрд▓рд┐рдирдХреНрд╕ 2.2.0 (C) void __switch_to(struct task_struct *prev, struct task_struct *next) { 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)); if (next->mm->segments != prev->mm->segments) asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt)); { unsigned long new_cr3 = next->tss.cr3; if (new_cr3 != prev->tss.cr3) asm volatile("movl %0,%%cr3": :"r" (new_cr3)); } 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 (рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ) #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" "movl %3,%%esp\n\t" "movl $1f,%1\n\t" "pushl %4\n\t" "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) 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)); loadsegment(fs, next->fs); loadsegment(gs, next->gs); if (next->debugreg[7]){ loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); loaddebug(next, 3); 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 рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рдХреЛрдбрд╛рдВрддрд░рдХ) #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" "movl %5,%%esp\n\t" "movl $1f,%1\n\t" "pushl %6\n\t" "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) 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_TLS(next, cpu); asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) { loadsegment(fs, next->fs); loadsegment(gs, next->gs); } if (unlikely(next->debugreg[7])) { loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); loaddebug(next, 3); 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) #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" "movq %P[threadrsp](%[next]),%%rsp\n\t" "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"
рдкреБрд░рд╛рдиреЗ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдкреБрд░рд╛рдиреЗ рдХрд╛рд░реНрдп рдХреЗ TSS рдореЗрдВ рд╕рд╣реЗрдЬрддрд╛ рд╣реИред рдЗрдирдкреБрдЯ рдСрдкрд░реЗрдВрдб рд╕реЗрдХреНрд╢рди рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирдИ рдиреЛрдЯреЗрд╢рди рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ: рдпрд╣ [threadrsp]
task_struct рдХреЗ рдЕрдВрджрд░ thread.rsp рдХреА рдбрд╛рдпрд░реЗрдХреНрдЯ рдСрдлрд╕реЗрдЯ рд╣реИред %P
dereferences рдкреНрд░рдмрд▓: рдереНрд░реЗрдбрдкреЙрдЗрдВрдЯ рдкреЙрдЗрдВрдЯрд░ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдЕрджреНрдпрддрди SP рдареАрдХ рд╕реЗ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИред "movq %P[threadrsp](%[next]),%%rsp\n\t"
рдирдП рдХрд╛рд░реНрдп рдХреЗ рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред "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_struct
RDI рдХреЛ рдкрд┐рдЫрд▓реА рд╕реНрдЯреНрд░реАрдо рдмрдЪрд╛рддрд╛ рд╣реИ ред EAX рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдЕрдВрддрд┐рдо рдирд┐рд░реНрджреЗрд╢ C рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реИ __switch_to
, рдЬреЛ prev
EAX рдкрд░ рд▓реМрдЯрддрд╛ рд╣реИред "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) 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); { 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; } 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; } 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); if (unlikely(next->debugreg7)) { loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); loaddebug(next, 3); 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; }
рд╕рдВрд╕реНрдХрд░рдг 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) #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" "movq %P[threadrsp](%[next]),%%rsp\n\t" "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) __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; if (preload_fpu) prefetch(next->fpu.state); 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); if (preload_fpu) clts(); arch_end_context_switch(next_p); if (unlikely(fsindex | next->fsindex | prev->fs)) { loadsegment(fs, next->fsindex); if (fsindex) prev->fs = 0; } 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; 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); 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); 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 #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 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 ENTRY(__switch_to_asm) UNWIND_HINT_FUNC pushq %rbp pushq %rbx pushq %r12 pushq %r13 pushq %r14 pushq %r15 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 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 ( рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕реНрд░реЛрдд ) __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); this_cpu_write(current_task, next_p); this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p)); update_sp0(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); #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); } 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 рдХреЛ рдЪрд╛рд░ рджрд┐рди рдмрд╛рдж рдкреВрд░рд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛редрдЬреИрд╕реЗ рд╣реА рд╡реЗ рдЙрдкрд▓рдмреНрдз рд╣реЛрдВрдЧреЗ рдореИрдВ рдЕрдиреНрдп рдкреНрд░рд╢реНрди рдЬреЛрдбрд╝ рджреВрдВрдЧрд╛ред