Apa isi alamat fisik 0 di x86 Linux?

12

Saya tidak yakin apakah pertanyaan ini harus masuk ke sini atau di reverseengineering.stackexchange.com

Mengutip dari wikipedia :

Dalam prosesor 8086, tabel interrupt disebut IVT (interrupt vector table). IVT selalu berada di lokasi yang sama dalam memori, mulai dari 0x0000 hingga 0x03ff, dan terdiri dari 256 byte mode nyata pointer jauh (256 × 4 = 1024 byte memori).

Ini yang saya temukan di monitor qemu:

(qemu) xp/128xw 0
0000000000000000: 0xf000ff53 0xf000ff53 0xf000e2c3 0xf000ff53
0000000000000010: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000020: 0xf000fea5 0xf000e987 0xf000d62c 0xf000d62c
0000000000000030: 0xf000d62c 0xf000d62c 0xf000ef57 0xf000d62c
0000000000000040: 0xc0005526 0xf000f84d 0xf000f841 0xf000e3fe
0000000000000050: 0xf000e739 0xf000f859 0xf000e82e 0xf000efd2
0000000000000060: 0xf000d648 0xf000e6f2 0xf000fe6e 0xf000ff53
0000000000000070: 0xf000ff53 0xf000ff53 0xf0006aa4 0xc0008930
0000000000000080: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000090: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000c0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000d0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000e0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000100: 0xf000ec59 0xf000ff53 0xf000ff53 0xc0006730
0000000000000110: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000120: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000130: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000140: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000150: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000160: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000170: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000180: 0x00000000 0x00000000 0x00000000 0x00000000
0000000000000190: 0x00000000 0x00000000 0x00000000 0xf000ff53
00000000000001a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001c0: 0xf000d611 0xf000ec4e 0xf000ec4e 0xf000ec4e
00000000000001d0: 0xf000d61a 0xf000d623 0xf000d608 0xf000ec4e
00000000000001e0: 0xf000ff53 0x00000000 0xf000ff53 0xf000ff53
00000000000001f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53

Saya tidak yakin apa yang membuat nilai-nilai itu. Itu tidak terlihat seperti tabel deskriptor interupsi (mendereferensi nilai-nilai tersebut memberikan semua nol). Jadi apa yang sebenarnya saya lihat di sini?

rhodeo
sumber

Jawaban:

9

Apapun firmware yang tersisa mengandungnya.

Pada sistem modern yang ideal, prosesor tidak pernah masuk ke mode nyata sama sekali, seperti yang saya jelaskan dalam T&J SU berjudul: Mode apa yang dilakukan chip PC Intel 64-bit modern yang menjalankan sektor boot? , KiB pertama dari memori fisik sama tidak relevannya seperti yang dibuat oleh Johan Myréen dalam jawaban lain di sini. Tetapi banyak firmware modern (masih) memiliki dukungan kompatibilitas , yang berarti itu

  • mereka dapat mundur (ya, kembali , mengingat bahwa mereka beralih langsung dari mode tidak nyata ke mode terlindungi) dari mode terlindungi ke mode nyata untuk menjalankan perangkat lunak sistem yang ditulis untuk mode nyata, seperti program boot PC / AT gaya lama di MBR dan VBR; dan
  • mereka menyediakan API firmware mode real lama dan mengatur semua struktur data untuk API tersebut, yang diandalkan oleh perangkat lunak sistem yang disebutkan di atas.

Salah satu struktur data tersebut adalah mode IVT nyata. API firmware mode nyata lama didasarkan pada intinstruksi, dan IVT mode nyata diisi oleh firmware sebagai bagian dari inisialisasi dengan petunjuk ke berbagai rutinitas penanganan firmware untuk instruksi tersebut.

Perangkat lunak sistem mode terproteksi tidak memerlukan API firmware mode real lama, dan tidak pernah menjalankan prosesor dalam mode real, sehingga mode real IVT dalam memori fisik 1KiB pertama tidak digunakan. (mode terlindungi v8086 tidak membahas alamat fisik 00000000 dan ke atas, ingat. Alamat alamat logis 00000000 dan ke atas, yang diterjemahkan oleh tabel halaman.) Dalam sistem EFI modern, firmware menyerahkan peta memori memori fisik ke sistem operasi. bootstrap, memberitahukan bagian mana yang dicadangkan ke firmware untuk keperluannya sendiri mode API, dan bagian mana sistem operasi bebas untuk hanya pergi ke depan dan digunakan untuk kumpulan memori fisik. Secara teori, halaman pertama dari memori fisik dapat berada dalam kategori yang terakhir.

Dalam praktiknya, pertama, firmware seringkali menandai halaman pertama memori fisik sebagai "kode layanan booting", yang berarti bahwa sistem operasi dapat mengklaimnya dan langsung menggunakannya dan menggunakannya sebagai bagian dari kumpulan memori fisiknya, tetapi hanya setelah boot layanan waktu dari firmware EFI telah dimatikan oleh sistem operasi dan firmware dikurangi menjadi menyediakan layanan run-time saja. Contohnya dapat dilihat di log kernel Linux (dengan add_efi_memmapopsi) yang ditunjukkan oleh Finnbarr P. Murphy:

[0,000000] efi: mem00: type = 3, attr = 0xf, range = [0x000000000000000000-0x000000000000001000) (0MB)
yang xe decode dengan program lain dalam bentuk yang lebih dapat dibaca manusia sebagai:

[# 00] Jenis: EfiBootServicesCode Attr: 0xF
      Phys: 0000000000000000-0000000000001000
      Virt: 0000000000000000-0000000000001000

Dalam praktiknya, kedua, Linux secara eksplisit mengabaikan rentang memori fisik ini bahkan jika firmware mengatakan bahwa ia dapat melanjutkan dan menggunakannya. Anda akan menemukan bahwa baik pada firmware EFI dan non-EFI, begitu Linux memiliki peta memori fisik, ia akan menambalnya ( dalam fungsi yang disebuttrim_bios_range ), menghasilkan pesan log kernel seperti:

[0,000000] e820: perbarui [mem 0x00000000-0x00000fff] dapat digunakan ==> dicadangkan

Ini tidak banyak untuk mengatasi firmware EFI modern, di mana mode IVT nyata bukan bagian dari API firmware, karena ini untuk mengatasi firmware PC98 lama, di mana itu adalah bagian dari API firmware tetapi firmware melaporkannya (melalui API yang sama itu sendiri) sebagai memori fisik yang tersedia untuk ditimpa oleh sistem operasi.

Jadi, sementara dalam teori, rentang memori fisik dapat berisi kode atau data yang berubah-ubah, tergantung dari kebutuhan sesaat dari pengalokasi memori kernel dan memori virtual yang diurutkan berdasarkan permintaan; dalam prakteknya, Linux membiarkannya tidak tersentuh sebagaimana firmware awalnya mengaturnya.

Dan pada sistem Anda, firmware telah mengisinya dengan entri mode IVT nyata. Entri mode IVT nyata hanya 16:16 pointer jauh, tentu saja, dan jika Anda melihat memori Anda menggunakan hexdump 2-byte Anda benar-benar dapat melihat ini dengan cukup jelas. Beberapa contoh:

  • Sebagian besar entri IVT Anda mengarah ke F000: FF53, sebuah alamat di area ROM firmware mode nyata. Mungkin ini adalah dummy rutin yang tidak lebih dari satu iret.
  • Entri IVT 1E menunjuk ke F000: 6AA4, sebuah tabel di area ROM yang sama.
  • Entri IVT 1F menunjuk ke C000: 8930, sebuah tabel di area firmware ROM video mode nyata.
  • Entri IVT 43 poin ke C000: 6730, tabel lain dalam mode firmware video ROM mode nyata.

Bacaan lebih lanjut

JdeBP
sumber
Tidak, maksud saya apa yang saya tulis. Manual Pengembangan Perangkat Arsitektur Intel volume 3 bab 20 § 2.
JdeBP
Nah, sekarang sudah, karena memang begitu; sebagai kalimat pertama dari bagian itu menjelaskan. Saya curiga dari ini bahwa tidak dikenalnya singkatan umum "v8086" adalah semacam shibboleth. (-:
JdeBP
Anda perlu belajar cara membaca kata benda atributif. Atau belajar hidup tanpa sup jamur.
JdeBP
7

Arsitektur prosesor 8086 asli (diimplementasikan sebagai Real Mode dalam prosesor 80286+) tidak memiliki relevansi untuk Linux, yang beroperasi dalam Mode Terlindungi. Tidak ada tabel vektor interupsi di alamat fisik 0, sebagai gantinya Tabel Interrupt Descriptor yang berisi Interrupt Descripors digunakan. IDT dapat ditemukan di mana saja dalam memori.

Kernel Linux mendapatkan peta memori fisik dari firmware (BIOS atau EFI) yang memberi tahu frame halaman memori fisik mana yang dapat digunakan dan mana yang dicadangkan atau tidak ada. Kisaran bingkai halaman yang dapat digunakan tidak bersebelahan, tetapi biasanya memiliki lubang besar di dalamnya. Secara tradisional, kernel x86 Linux telah melewatkan awal memori fisik, bahkan jika itu ditandai sebagai dapat digunakan. Dengan demikian, alamat fisik 0 tidak digunakan oleh kernel Linux.

Johan Myréen
sumber
Ini masuk akal. Adakah yang tahu dari konten sisa di halaman yang tidak digunakan itu?
rhodeo
Googling untuk 53 ffmengungkapkan bahwa ini kemungkinan besar sebenarnya merupakan tabel vektor interupsi Mode Riil 8086 yang dibuat oleh firmware atau boot loader.
Johan Myréen
4

Memori pembuangan

Berikut adalah cara alternatif untuk membuang konten memori di dalam sistem vs harus melakukannya secara eksternal:

$ head /dev/mem | hexdump -C
00000000  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
00000010  53 ff 00 f0 53 ff 00 f0  cc e9 00 f0 53 ff 00 f0  |S...S.......S...|
00000020  a5 fe 00 f0 87 e9 00 f0  53 ff 00 f0 46 e7 00 f0  |........S...F...|
00000030  46 e7 00 f0 46 e7 00 f0  57 ef 00 f0 53 ff 00 f0  |F...F...W...S...|
00000040  22 00 00 c0 4d f8 00 f0  41 f8 00 f0 fe e3 00 f0  |"...M...A.......|
00000050  39 e7 00 f0 59 f8 00 f0  2e e8 00 f0 d4 ef 00 f0  |9...Y...........|
00000060  a4 f0 00 f0 f2 e6 00 f0  6e fe 00 f0 53 ff 00 f0  |........n...S...|
00000070  ed ef 00 f0 53 ff 00 f0  c7 ef 00 f0 ed 57 00 c0  |....S........W..|
00000080  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
...
...
000afea0  00 00 00 00 00 00 00 00  aa aa aa 00 aa aa aa 00  |................|
000afeb0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000b0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
000c0000  55 aa 40 e9 62 0a 00 00  00 00 00 00 00 00 00 00  |[email protected]...........|
000c0010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 49 42  |..............IB|

Analisis

Bagian atas di atas 000c0000 bisa jadi terkait dengan bootloader. Mengapa saya curiga ini? Kode 55aah di lokasi 000c0000biasanya dapat menjadi tanda dalam memori untuk hal-hal seperti pemicu BIOS untuk menjalankan bootloader sekunder.

Referensi: Boot Signature - BIOS

  ss # 1

Namun, mengingat bahwa 55aah ini terjadi dalam kisaran c0000h-effffh, maka kemungkinan besar bagian ini adalah Kepala Ekspansi PNP:

Referensi: Spesifikasi Boot BIOS

3.3 Perangkat dengan Header Ekspansi PnP

Semua perangkat IPL dengan ROM opsi harus berisi header ROM opsi yang valid yang berada di antara alamat memori sistem C0000h dan EFFFFh pada batas 2k dan dimulai dengan 55AAh. Boot perangkat hanya dapat dikontrol jika memiliki Header Ekspansi PnP. Header Ekspansi, yang alamatnya berada di dalam header ROM opsi standar pada offset + 1Ah, berisi informasi penting yang digunakan untuk mengonfigurasi perangkat. Ini juga berisi pointer ke kode dalam ROM opsi perangkat (BCV atau BEV) yang akan dipanggil oleh BIOS untuk melakukan booting dari perangkat. Lihat Lampiran A untuk struktur Header Ekspansi PnP. Ada dua cara perangkat IPL dengan PnP Expansion Header dapat di-boot. Itu harus mengandung BCV atau BEV.

53ff ...

Adapun data 53ffh yang ada di awal. Tidak jelas bagi saya apa itu sebenarnya. Lebih lanjut meneliti itu kemungkinan sesuatu bahwa kernel Linux menulis di sana setelah bootloading BIOS dari MBR diserahkan ke kernel Linux untuk boot.

Biasanya, bootloader akan memuat kernel ke dalam memori, dan kemudian melompat ke kernel. Kernel kemudian akan dapat mengambil kembali memori yang digunakan oleh bootloader (karena sudah melakukan tugasnya). Namun dimungkinkan untuk memasukkan kode OS dalam sektor boot dan menyimpannya setelah OS dimulai

Menggali lebih jauh saya dapat menemukan paragraf ini dari sebuah makalah penelitian berjudul: Injeksi Kode Berbahaya via / dev / mem :

1 Perangkat mem

/ dev / mem adalah antarmuka driver untuk memori yang dapat dialamatkan secara fisik. Maksud asli dari mem dan kmem adalah untuk membantu debugging kernel. Kita dapat menggunakan perangkat seperti perangkat karakter biasa, menggunakan lseek () untuk memilih offset alamat. Perangkat kmem serupa tetapi menyediakan gambar memori kernel dalam konteks pengalamatan virtual. Server Xorg memanfaatkan perangkat mem untuk mengakses memori video VESA serta Tabel Interupsi Vektor BIOS ROM (IVT) yang terletak di alamat fisik 0x00000000 untuk memanipulasi mode video dalam mode VM86. DOSEMU juga menggunakan ini untuk mengakses BIOS IVT untuk dapat membuat BIOS Interrupts untuk berbagai tugas (disk membaca, mencetak ke konsol, dll).

Referensi

slm
sumber