หน่วยประมวลผลหารหัสเคอร์เนลหลังจากถูกขัดจังหวะได้อย่างไร


13

เมื่อการขัดจังหวะเกิดขึ้นโปรเซสเซอร์จะดำเนินการกระบวนการปัจจุบันและเรียกใช้รหัสเคอร์เนลเพื่อจัดการการขัดจังหวะ โปรเซสเซอร์รู้ได้อย่างไรว่าจะเข้าไปยังเคอร์เนลอย่างไร

ฉันเข้าใจว่ามีตัวจัดการขัดจังหวะซึ่งสามารถติดตั้งสำหรับแต่ละบรรทัดขัดจังหวะ แต่เนื่องจากโปรเซสเซอร์ประมวลผล 'hardwired logic' เท่านั้นจึงต้องมีสถานที่ที่กำหนดไว้ล่วงหน้าซึ่งชี้ไปที่ interrupt handler เองหรือบางรหัสที่ประมวลผลก่อน handler (เนื่องจากอาจมีตัวจัดการหลายตัวสำหรับ interrupt line หนึ่งผมถือว่า หลัง)

คำตอบ:


13

ในการเริ่มต้นเคอร์เนลจะเริ่มต้นตารางเวกเตอร์ขัดจังหวะ (เรียกว่าตารางอธิบายขัดจังหวะหรือ IDT บน x86) ที่ชี้ไปที่จัดการขัดจังหวะสำหรับแต่ละบรรทัด

ก่อน 80286 IDT จะถูกเก็บไว้เสมอในที่อยู่ถาวร เริ่มต้นด้วย 80286, IDT ถูกโหลดโดยใช้LIDTคำแนะนำ

ตารางเวกเตอร์ขัดจังหวะชี้ไปที่ตัวจัดการเดียวต่อบรรทัดขัดจังหวะ ที่ถูกกล่าวว่าเคอร์เนลสามารถเลือกตัวอย่างเช่นจัดให้มีตัวจัดการขัดจังหวะที่ใช้งานประจำขัดจังหวะอื่น ๆ อีกหลายหรือให้จัดการเดียวที่ครอบคลุมบางส่วนหรือทั้งหมดขัดจังหวะ Linux ทำสิ่งเหล่านี้โดยจัดให้มีตัวจัดการการขัดจังหวะทั่วไปที่กำหนดว่าสายการขัดจังหวะใดถูกเรียกและค้นหาตัวจัดการดาวน์สตรีมที่เหมาะสมในการโทร


1
ดังนั้นโปรเซสเซอร์จึงใช้บรรทัดขัดจังหวะเป็นดัชนีให้กับ IDT วางรายการในพีซีและเริ่มดำเนินการ? แต่ไม่มีฟังก์ชั่นทั่วไปที่ทำงานก่อนตัวจัดการขัดจังหวะทั้งหมดหรือไม่ สำหรับ linux มันจะเป็น do_IRQ () นี่คือฟังก์ชั่นที่จุดเข้าใช้งานของ IDT ทุกจุดไม่ว่าจะเป็นสายอินเตอร์รัปต์หรือไม่?
Philipp Murry

@PhilippMurry ใช่ เคอร์เนลใช้ชุดของตัวจัดการขัดจังหวะของตัวเอง (ซึ่งอาจมีมากกว่าหนึ่งต่อบรรทัด) เพื่อจัดการกับการขัดจังหวะก่อนที่จะกลับไปที่รหัสการดำเนินการก่อนหน้านี้
Adam Maras

ตกลงดังนั้นจริง ๆ แล้วมีตัวจัดการขัดจังหวะสองประเภท: ประเภทที่ตัวประมวลผลเรียก (เสมอ do_IRQ ()) และประเภทที่เคอร์เนลเรียก (ตัวที่ฉันลงทะเบียนผ่าน request_irq ()) คุณสามารถเพิ่มคำตอบของคุณได้ไหม ฉันคิดว่าฉันจะยอมรับมัน :) ขอบคุณมาก
Philipp Murry

1
@PhilippMurry ฉันไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับวิธีที่ Linux จัดการกับการขัดจังหวะ (และวิธีที่ผู้พัฒนาเคอร์เนลแตะลงในระบบนั้น) แต่ฉันได้เพิ่มข้อมูลเพิ่มเติมในแง่กว้างเกี่ยวกับวิธีที่เมล็ดสามารถจัดการ ISR ของตัวเองได้
Adam Maras

12

ใช่มีเป็นสถานที่ที่กำหนดไว้ล่วงหน้าที่มีอยู่ของรหัสที่จะข้ามไปยัง: ภาพเวกเตอร์ขัดจังหวะ อาจเป็นตำแหน่งเฉพาะในหน่วยความจำกายภาพ (8088), ตำแหน่งเฉพาะในหน่วยความจำเสมือน, ลงทะเบียนโปรเซสเซอร์, ตำแหน่งในหน่วยความจำที่ระบุโดยการลงทะเบียน (ARM, 386), ...

รายละเอียดแตกต่างกันไปตามโปรเซสเซอร์ที่แตกต่างกัน แต่องค์ประกอบหลักทั่วไปในการจัดการอินเตอร์รัปต์ในโปรเซสเซอร์คือ:

  • มาสก์อินเตอร์รัปต์ (ดังนั้นการขัดจังหวะที่ตามมาใด ๆ จะต้องรอ)
  • ตั้งค่าโหมดตัวประมวลผลเป็นเคอร์เนลหรือโหมดขัดจังหวะ (หากตัวประมวลผลมีโหมดดังกล่าว)
  • บันทึกค่าของตัวนับโปรแกรมไปยังตำแหน่งที่รู้จัก (รีจิสเตอร์หรือหน่วยความจำ)
  • อาจบันทึกค่าของการลงทะเบียนอื่นหรือสลับระหว่างการลงทะเบียนธนาคาร)
  • ดำเนินการคำสั่งถัดไป (ที่ค่า PC ใหม่)

1

อีกสองคำตอบ (ในขณะที่เขียน) พูดคุยเกี่ยวกับการขัดจังหวะและ IDT อย่างไรก็ตามนี่เป็นสิ่งที่ถูกต้อง แต่ในซีพียู Intel-esque ที่ทันสมัยมีไม่น้อยกว่าสามวิธีในการเรียกใช้เคอร์เนล

วิธีที่ # 1: การขัดจังหวะ

นี่คือคำอธิบายข้างต้น คุณตั้งค่ารายการในตารางอธิบาย / ขัดจังหวะเวกเตอร์จากนั้นรันซอฟต์แวร์ขัดจังหวะเพื่อป้อนเคอร์เนล

ข้อได้เปรียบหลักของวิธีนี้คือเคอร์เนลทั่วไปต้องสามารถจัดการกับการขัดจังหวะได้และมันทำงานกับฮาร์ดแวร์โบราณ

วิธีที่ # 2: เรียกประตู

ประตูการโทรเป็นตัวเลือกกลุ่มชนิดพิเศษ เป้าหมายของการโทรจะต้องโหลดในตารางตัวบอกส่วนโกลบอลหรือโลคัล (GDT และ LDT ตามลำดับ) หากคุณดำเนินการคำสั่งการโทรแบบไกลโดยใช้เกตการโทรเป็นส่วน (การชดเชยการโทรจะถูกละเว้น) สิ่งนี้จะช่วยให้คุณสามารถเรียกรหัสที่มีสิทธิพิเศษมากขึ้น ประตูการโทรมีความยืดหยุ่นสูง สถาปัตยกรรม IA-32 มีสี่ระดับสิทธิ์และประตูการโทรให้คุณโทรได้ทุกระดับ

ฉันไม่เชื่อว่าลีนุกซ์เคยใช้เกตประตู แต่ Windows 95 ทำได้ บริการเคอร์เนล Win95 ( krnl386.exeและkernel.dll) ทำงานในโหมดผู้ใช้จริง (เสียงเรียกเข้า 3) ระดับสิทธิ์ใช้งานสูงสุด (แหวน 0) ใช้สำหรับไดรเวอร์เท่านั้นและ microkernel ซึ่งดำเนินการสลับกระบวนการเท่านั้น การโทรเข้าไปในไดรเวอร์ทำได้โดยใช้ call gates สิ่งนี้ได้รับอนุญาตให้ใช้รหัส 16 บิตแบบดั้งเดิม (ซึ่งมีจำนวนมาก!) เพื่อใช้ไดรเวอร์ Win95 เพียงแค่ใช้การโทรระยะไกลแบบมาตรฐานเช่นเดียวกับที่พวกเขาทำ

การป้องกันตาราง descriptor ทั่วโลกไม่เพียงพอเป็นสาเหตุของการหาประโยชน์หลาย ๆ อย่างของ Windows 95 ซึ่งจัดการติดตั้งประตูการโทรของตัวเองด้วยการเขียนทับหน่วยความจำ

วิธีที่ # 3: SYSCALL / SYSRET และ SYSENTER / SYSEXIT

นี่เป็นคำสั่งสองชุดที่คิดค้นโดยอิสระจาก AMD และ Intel แต่โดยพื้นฐานแล้วพวกเขาทำสิ่งเดียวกัน SYSCALL / SYSRET มาก่อนและเป็น AMD เท่านั้น SYSENTER / SYSEXIT เป็น Intel แต่ AMD นำมาใช้ทันที ดังนั้นฉันจะอธิบาย SYSENTER / SYSEXIT

ซึ่งแตกต่างจาก call gates, SYSENTER สามารถใช้เพื่อถ่ายโอนไปยัง ring 0 เท่านั้นและสามารถถ่ายโอนไปยังที่เดียวเท่านั้น อย่างไรก็ตามมันมีข้อดีของการมีความหน่วงต่ำมากเนื่องจากไม่เหมือนกับการโทรหรือการขัดจังหวะโดยไม่ได้สัมผัสกับกองซ้อน

ตำแหน่งการถ่ายโอนถูกตั้งค่าโดยใช้การลงทะเบียนแบบเฉพาะสามแบบ: หนึ่งรายการสำหรับข้อมูลเซ็กเมนต์และอีกหนึ่งรายการสำหรับตัวชี้คำสั่งและตัวชี้สแต็กของรหัสเคอร์เนล เนื่องจากไม่มีสิ่งใดที่ "ผลัก" ลงบนสแต็กรหัสโหมดผู้ใช้มีหน้าที่บอกเคอร์เนลว่าจะกลับไปที่ใดโดยส่งตัวชี้คำสั่งการส่งคืนและตัวชี้สแต็กในการลงทะเบียน เคอร์เนลมีหน้าที่กู้คืนตัวชี้สแต็กและคำสั่ง SYSEXIT คืนค่าตัวชี้คำสั่ง

ข้อมูลเพิ่มเติมเกี่ยวกับคำแนะนำของ SYSENTER และ SYSEXIT

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.