Skip to content

معالجاتُ المقاطعات

x86_64 وحدَها — قُلْها قبلَ أن تكتب

مُعدِّلُ دالة مقاطعة يُخفَّضُ على x86_64 حصرًا. وقد قِيسَ الرفضُ على الثلاثةِ الأخرى — i686 وaarch64 وriscv64 — كلُّها تُخفِقُ بـSEM046. والسببُ المكتوبُ في التشخيصِ نفسِه: عقدُ i386 مختلفٌ (رمزُ خطأٍ i32 وعودةٌ بـiret). فإن كانت نواتُك ٣٢-بت فهذه الصفحةُ لا تخدمُك بعد.

الهدف: تكتبُ معالجَ مقاطعةٍ بلغةِ ص، فيتولّى المترجّمُ كعبَ الدخولِ والخروجِ كاملًا — حفظُ السجلّاتِ المتطايرة، وتسويةُ المكدَّسِ لرمزِ الخطأ، والعودةُ بـiretq — ثمّ تُسجِّلُه في جدولِ المقاطعات.

العقد

دالة مقاطعة اسم(رقم إطار_المقاطعة)
دالة مقاطعة اسم(رقم إطار_المقاطعة، رقم رمز_الخطأ)
  • العائدُ فراغ. لا ارجع بقيمة.
  • المعاملُ الأوّلُ إلزاميّ: إطارُ المقاطعة.
  • المعاملُ الثاني اختياريّ: رمزُ الخطأ — للمصائدِ التي يدفعُه المعالجُ لها (‏#PF مثلًا). ولا ثالثَ.
  • لا يُنادى ولا يُؤخَذُ قيمةً. عنوانُه يُؤخَذُ بـعنوان_رمز.

الوصفة

sad
@رمز("idt_ptr") متغير ساكن واصف_الجدول مصفوفة[10]

@رمز("isr_timer") دالة مقاطعة نبضة(رقم إطار)
    اكتب_منفذ(0x20، 0x20)          # نهايةُ المقاطعةِ إلى المتحكّم
نهاية

@رمز("isr_pf") دالة مقاطعة عطل_صفحة(رقم إطار، رقم رمز_الخطأ)
    بينما (صحيح)
        أسبت_المعالج()
    نهاية
نهاية

@رمز("kmain") دالة لا_ترجع نواة()
    هيئ_جدول_مقاطعات()
    سجل_معالج_مقاطعة(32، عنوان_رمز("isr_timer"))
    سجل_معالج_مقاطعة(14، عنوان_رمز("isr_pf"))
    حمل_جدول_مقاطعات(عنوان_رمز("idt_ptr"))
    بينما (صحيح)
        أسبت_المعالج()
    نهاية
نهاية
bash
$ sad-build مقاطعات.ص --حرّ --بلا-رئيسية \
      --هدف=x86_64-unknown-none-elf --أظهر-llvm -o مقاطعات.ll

لا مخرَجَ، والرمزُ صفر. وفي الـIR:

llvm
@idt_ptr = global [10 x i8] zeroinitializer, align 16

; Function Attrs: noredzone
define x86_intrcc void @isr_timer(ptr byval({ i64, i64, i64, i64, i64 }) %"إطار") #0

define x86_intrcc void @isr_pf(ptr byval({ i64, i64, i64, i64, i64 }) %"إطار",
                               i64 %"رمز_الخطأ") #0

  call void asm sideeffect "lidt ($0)", "r,~{memory}"(i64 ptrtoint (ptr @idt_ptr to i64))

أربعةُ شواهدَ في هذا المقتطف:

الشاهدماذا يعني
x86_intrccاتّفاقيّةُ نداءِ المقاطعة — الكعبُ مولَّدٌ، والعودةُ iretq
byval({ i64 ×5 })إطارُ المقاطعةِ يُمرَّرُ بالقيمةِ كما يضعُه المعالجُ على المكدَّس
noredzoneلا منطقةَ حمراء — المقاطعةُ تدوسُها لو بقيت
lidt ($0)حمل_جدول_مقاطعات تُخفَضُ تجميعًا مضمَّنًا لا نداءَ مكتبة

الأخطاءُ التي ستراها

كلُّ ما يلي مخرَجٌ حقيقيٌّ لا صياغةٌ تقريبيّة.

ناديتَ المعالجَ بدل أخذِ عنوانِه

error: [خطأ نوع] [SEM046] «معالج_عام»: معالجُ المقاطعةِ لا يُنادى — خذ عنوانَه
بـ«عنوان_رمز» وسجّله في جدولِ المقاطعات
  → صرّح المعالج «دالة مقاطعة اسم(رقم إطار_المقاطعة)» بعائد فراغ ومعامل أوّل
    إلزاميّ (ورمز خطأ اختياريّ ثانٍ)، وخذ عنوانه بـ«عنوان_رمز» بدل ندائه،
    وصرّف للوضع الحرّ على هدف x86_64.

أغفلتَ إطارَ المقاطعة

error: [خطأ نوع] [SEM046] «معالج_عام»: معالجُ المقاطعةِ يأخذ إطارَ المقاطعةِ
معاملًا أوّلَ إلزاميًّا، ورمزَ الخطأِ معاملًا ثانيًا اختياريًّا لا أكثر (وُجد 0)

بنيتَ لهدفٍ غيرِ x86_64

error: [SEM046] «نبضة»: بوّابةُ المقاطعةِ تُخفَّض على x86_64 حصرًا في المرحلةِ
الأولى — عقدُ i386 مختلفٌ (رمزُ خطأٍ i32 وعودةٌ بـiret) والهدفُ هنا:
i686-unknown-unknown-elf

نسيتَ واصفَ الجدولِ في حمل_جدول_مقاطعات

error: [SEM020] حمل_جدول_مقاطعات: يتطلّب مؤشّر واصف الجدول (الحدّ+القاعدة) في
الوضع الحرّ

الوسيطُ اختياريٌّ مستضافًا وإلزاميٌّ حرًّا — وهو مثالٌ على قاعدةٍ يحرسُها tests/system/lowlevel_freestanding/test_os_core_arity.py في الاتّجاهَين.

ورتبةُ المدمَجاتِ مفروضةٌ في الاتّجاهَين

اكتب_سجل_تحكم(4096) بوسيطٍ ناقصٍ كانت تخرجُ بصفرٍ ولا تُصدِرُ شيئًا: النداءُ يتبخّرُ صامتًا. وبوسيطٍ زائدٍ تُقبَلُ ويُهمَلُ الزائد. وذاك أخطرُ صنفِ عيوبٍ في نواةٍ: سطرُ أمانٍ «يُنفَّذ» وهو غيرُ موجود. اليومَ الناقصُ خطأُ تصريف:

error: [SEM005] الدالة 'اكتب_سجل_تحكم' تتوقّع 2 من المعاملات، لكن مُرِّر 1

لماذا وُجِدَ المُعدِّلُ أصلًا

معالجُ المقاطعةِ المكتوبُ بلغةِ ص كان يدخلُ ولا يستطيعُ الرجوع: لا كعبَ دخولٍ ولا خروج، فلا مقاطعةَ مؤقّت، فلا جدولة، فلا نظامَ تشغيل. والمُعدِّلُ يسدُّ ذلك الثقبَ الواحدَ بإحالةِ الكعبِ إلى x86_intrcc في LLVM. تفصيلُ المقيسِ في tests/system/lowlevel_freestanding/test_interrupt_handler_modifier.py (RFC 0059، الفجوة ح٢).

ما يلي

مُرخَّص بموجب رخصة MIT