2012-05-14 12 views
6

Kendi başıma bir çekirdek yazıyorum ve ilk sayfa hatası kesme işleyicisinden sonra, IRET yürütüldüğünde, bir kesme 13'e neden oluyor (genel koruma) ve hata kodu 0x18'dir. Neyin yanlış olduğunu bilmiyorum, yığında itilen içerik cpu'dan geliyor.Neden bir sayfa hata işleyicisinden kaynaklanan hata kesme 13 (genel koruma hatası) ve 0x18 hata kodu oluşturuyor?

Kesinti oluştuğunda kayıt durumu ve yazmaçların depolandığı bellek. Ayrıca, IRET, bir sayfa hatası kesme işleyicisinden döndürülür.

% ESP'nin IRET yürütülmeden ve kesilmeden önce aynı olduğundan emin olun. (Btw 8 veya 0x18?)

enter image description here

enter image description here

cevap

7

istisna büyük olasılıkla IRET kaydedilen bölüm kayıtlarından birini geri yüklemek için başarısız olduğunu o zaman, kendisi IRET geliyorsa, ancak değer bir şekilde olduğunu yanlış. Eğer (yeniden) korumalı modda kayıt başlatıldı asla veya işleyici IRET yapmadan önce kötü bir değere ayarlayın ya da bir şey GDT oldu çünkü

DÜZENLEME ... yanlış olabilir: resimde itibaren belirgin var IRET çalıştırılmadan önce sayfa hata işleyicisi özel durum kodunu (ESP adresindeki 4 değeri) kaldırmamıştır. Ve böylece IRET, EIP için yeni değer, CS için yeni değer olarak 0x1000018 ve EFLAGS için yeni değer olarak 0x23 olarak yorumlanır, oysa bu üç kayıt için 0x1000018, 0x23 ve 0x3206 kullanıyor olmalıdır. Açıkçası, bir veri segmenti seçicisi (0x1000018'in kesilmesinden sonra 0x0018 olarak yorumlanır), CS'a yüklenemez ve bu da #GP (0x18) neden olur.

+0

Ben başlatmak gerektiğini kaydolun "Eğer (yeniden) asla çünkü yanlış olabilir korumalı modda kayıt başlatıldı"? –

+0

Tüm segment kayıtlarının korumalı modda düzgün şekilde başlatılması gerekir (CS, DS, ES, SS, FS, GS). Aslında şu anda, kodunuz hakkında daha fazla şey bilmeden tam olarak neyin yanlış olduğunu söylemek zor. Kodu yaz. –

+0

'IRET' açıklaması, neyin yanlış olabileceğine dair bazı ipuçları vermelidir. #GP (seçici) 'ye giden tüm koşullara bakın. –

2

Alexey genişletmek:

bazı kesmeler (ama diğerlerini) gerçekleşmesi, otomatik olarak yığınına 4 bayt hata kodunu itin. Sayfa hatası bunlardan biri.

Bu hata kodu, interrupt hakkında ek bilgi içerir.

Intel Manual Volume 3 System Programming Guide - 325384-056US September 2015 Tablo 6-1. "Korumalı Mod İstisnaları ve Kesmeleri" sütunu "Hata Kodu", hangi kesintilerin hata kodunu ittiğini ve hangilerinin tam olarak yapılmadığını gösterir.

38.9.2.2 "Sayfa Hata Hata Kodları" hatanın ne anlama geldiğini açıklar.

pop %eax 
/* Do something with %eax */ 
iret 

Yoksa hata kodunu gelmesini istemiyorsanız:

Yani ya gerekecektir

add $4, %esp 
iret 

minimal Örneğin, this page handler görmek ve pop dışında yorum deneyin.

Yukarıdakileri, yığınının çıkarılması gerekmeyen bir Division error exception ile karşılaştırın.

Basitçe int $14 yaparsanız, fazladan bir baytın itilmediğini unutmayın: bu yalnızca gerçek istisnada gerçekleşir.

Bununla başa çıkmanın düzgün bir yolu, bir şeyleri tekdüze hale getirmek için bunu yapmayan kesmeler için bir sahte hata kodunu 0 zorlamaktır. James Molloy'un öğreticisi does exactly that.

Linux çekirdeği 4.2 benzer bir şey gibi görünüyor.

trace_idtentry page_fault do_page_fault has_error_code=1 

ve sonra aynı dosya üzerinde kullanır: arch/x86/entry/entry64.S o modelleri altında has_error_code Interrupt'ları itmek has_error_code=0 yapar

.ifeq \has_error_code 
pushq $-1 /* ORIG_RAX: no syscall to restart */ 
.endif 

.

İlgili soru: Do I have to pop the error code pushed to stack by certain exceptions before returning from the interrupt handler?