読み物

読み物

ACM課金でなやむ

# 64bitUEFIでxv6を動かす方法(ブートローダー編)

https://pibvt.hateblo.jp/entry/2018/09/15/010757

x86_64にはx86に加えて、さらに動作モードが2つあるらしい。CbC_xv6はどれだ?

  • Long mode
  • Protected mode

動作モード -> CPUの動作モード

Compatibility modeってなんだ?Protected modeとは違うのか。 その辺りの話はIntel SDM vol3に書いてあると記事が言っている。

https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html

なんかいっぱいマニュアルある…どれだ

と思ったら記事にちゃんと書いてあった。感謝。

Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3 (3A, 3B, 3C & 3D): System Programming Guide

同じ名前のドキュメントはないけど多分これに載ってるのでは。

1
2
Intel® 64 and IA-32 Architectures Software Developer’s Manual
Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4

3.1 MODES OF OPERATIONにありそう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
3.1 MODES OF OPERATION
The IA-32 architecture supports three basic operating modes: protected mode, real-address mode, and system management mode. The operating mode determines which instructions and architectural features are accessible:
 Protected mode  This mode is the native state of the processor. Among the capabilities of protected mode is the ability to directly execute real-address mode 8086 software in a protected, multi-tasking environment. This feature is called virtual-8086 mode, although it is not actually a processor mode. Virtual-8086 mode is actually a protected mode attribute that can be enabled for any task.
 Real-address mode  This mode implements the programming environment of the Intel 8086 processor with extensions (such as the ability to switch to protected or system management mode). The processor is placed in real-address mode following power-up or a reset.
 System management mode (SMM)  This mode provides an operating system or executive with a transparent mechanism for implementing platform-specific functions such as power management and system security. The processor enters SMM when the external SMM interrupt pin (SMI#) is activated or an SMI is received from the advanced programmable interrupt controller (APIC).
In SMM, the processor switches to a separate address space while saving the basic context of the currently running program or task. SMM-specific code may then be executed transparently. Upon returning from SMM, the processor is placed back into its state prior to the system management interrupt. SMM was introduced with the Intel386TM SL and Intel486TM SL processors and became a standard IA-32 feature with the Pentium processor family.

3.1.1 Intel® 64 Architecture
Intel 64 architecture adds IA-32e mode. IA-32e mode has two sub-modes.
These are:
 Compatibility mode (sub-mode of IA-32e mode)  Compatibility mode permits most legacy 16-bit and 32-bit applications to run without re-compilation under a 64-bit operating system. For brevity, the compatibility sub-mode is referred to as compatibility mode in IA-32 architecture. The execution environment of compati- bility mode is the same as described in Section 3.2. Compatibility mode also supports all of the privilege levels that are supported in 64-bit and protected modes. Legacy applications that run in Virtual 8086 mode or use hardware task management will not work in this mode.
Compatibility mode is enabled by the operating system (OS) on a code segment basis. This means that a single 64-bit OS can support 64-bit applications running in 64-bit mode and support legacy 32-bit applications (not recompiled for 64-bits) running in compatibility mode.
Compatibility mode is similar to 32-bit protected mode. Applications access only the first 4 GByte of linear- address space. Compatibility mode uses 16-bit and 32-bit address and operand sizes. Like protected mode, this mode allows applications to access physical memory greater than 4 GByte using PAE (Physical Address Exten- sions).
 64-bit mode (sub-mode of IA-32e mode)  This mode enables a 64-bit operating system to run applica- tions written to access 64-bit linear address space. For brevity, the 64-bit sub-mode is referred to as 64-bit mode in IA-32 architecture.
64-bit mode extends the number of general purpose registers and SIMD extension registers from 8 to 16. General purpose registers are widened to 64 bits. The mode also introduces a new opcode prefix (REX) to access the register extensions. See Section 3.2.1 for a detailed description.
64-bit mode is enabled by the operating system on a code-segment basis. Its default address size is 64 bits and its default operand size is 32 bits. The default operand size can be overridden on an instruction-by-instruction basis using a REX opcode prefix in conjunction with an operand size override prefix.
REX prefixes allow a 64-bit operand to be specified when operating in 64-bit mode. By using this mechanism, many existing instructions have been promoted to allow the use of 64-bit registers and 64-bit addresses.

デフォルトはLong modeである。

IA-32e modeのsub-modeであるLong mode(64-bit mode)からProtected modeへ移行するには、 IA-32e modeのsub-modeであるCompatibility modeへ移行する必要がある。

Intel 8086ってなんだ。CPUです、くらいしかわからない。 x86アーキテクチャの最初のCPUらしい。x86の代表格といったところだろうか。 Protected modeはvirtual-8086 modeとも言われるよう。x86のOSを動かしたくば、Protected modeにせよという感じだろう。

UEFIの便利な点の1つとして、HDD,USBメモリ上のFATファイルシステムを認識できることが挙げられます。

ええ!これはUEFIの特徴だったのか。ということは僕がBIOSだと思っていたものは全てUEFIだったということだ。(そういうことだよね?)

まずは、ELF展開部分のソースコードを見ていきます。

ELFって何。実行ファイルの形式らしい。 何か適当に実行ファイルをfileしてみる。ELF 64-bit LSB pie executableと書かれている。

1
2
file /usr/sbin/zic
/usr/sbin/zic: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=912bc1a6c1d7e4c7fc79dbdb5a1ea1caf82c0488, for GNU/Linux 3.2.0, stripped

「Executable and Linking Format」の略

ちなみにM1 Macbookの場合

1
2
3
4
$ file /usr/sbin/zic
/usr/sbin/zic: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/usr/sbin/zic (for architecture x86_64):	Mach-O 64-bit executable x86_64
/usr/sbin/zic (for architecture arm64e):	Mach-O 64-bit executable arm64e

あれ、x86_64とarm64eの2つがある… クリーンインストールするとx86_64の方が消えるかも。というか適当に選んだけどzicってなんだ。

結局ELF展開部分ってなんだ。書いてあるソースを読めばわかるかも。 ELFをメモリーに展開する部分だとわかる。

ELFヘッダー、プログラムヘッダーってなんだ。多分実行ファイルのメタデータかな。実行ファイルのアドレスなどが入ってそう。

https://docs.oracle.com/cd/E19683-01/817-1232/chapter6-83432/index.html ここに書いてあるものと同一かはわからないが、同じようなものだと思う。 p_alignは何かというと

1
読み込み可能なプロセスセグメントは、ページサイズを基にして、p_vaddr と p_offset に対して同じ値を保持する必要があります。この構成要素は、セグメントがメモリーとファイルにおいて整列される値を与えます。値 0 と 1 は、整列が必要ないことを意味します。その他の値の場合、p_align は 2 の正整数累乗でなければならず、また p_vaddr は p_align を法として p_offset に等しくなければなりません。詳細は、プログラムの読み込み (プロセッサ固有)を参照してください。

んー、日本語だとよくわからないやつかなこれ。というかメモリアラインメントのalignならばアラインメントする時のサイズだと思う。

そういえば昨日GDT、IDTを調べてる途中で終わっちゃったな。

一般的にBIOS起動時はReal modeで動作しているため、OSは起動シーケンス内でGDTやIDT等を設定してProtected modeに移行します。

とのこと。Intel SDMで該当部分を探す。

(x87!?)

あった。ブログの時とは章の数が変わってる。自分が読んでるマニュアルはdalmoreに置いておこうかな。(dalmore:/mnt/ssd1/user/k228587/books/325462-sdm-vol-1-2abcd-3abcd.pdf) 10.8.5.4 Switching Out of IA-32e Mode Operation

1
2
3
4
5
6
7
8
To return from IA-32e mode to paged-protected mode operation operating systems must use the following sequence:
1. Switch to compatibility mode.
2. Deactivate IA-32e mode by clearing CR0.PG = 0. This causes the processor to set IA32_EFER.LMA = 0. The MOV CR0 instruction used to disable paging and subsequent instructions must be located in an identity-mapped page.
3. Load CR3 with the physical base address of the legacy page-table-directory base address.
4. Disable IA-32e mode by setting IA32_EFER.LME = 0.
5. Enable legacy paged-protected mode by setting CR0.PG = 1
6. A branch instruction must follow the MOV CR0 that enables paging. Both the MOV CR0 and the branch instruction must be located in an identity-mapped page.
Registers only available in 64-bit mode (R8-R15 and XMM8-XMM15) are preserved across transitions from 64-bit mode into compatibility mode then back into 64-bit mode. However, values of R8-R15 and XMM8-XMM15 are unde- fined after transitions from 64-bit mode through compatibility mode to legacy or real mode and then back through compatibility mode to 64-bit mode.

これでLong modeからProtected modeへ移行できるらしい。

1
2
3
4
5
6
7
8
void set_gdt(struct gdt *gdt,UINT32 type,UINT32 base,UINT32 lim){
  gdt->limit = (lim >> 12) & 0xFFFF;
  gdt->base1 = base & 0xFFFF;
  gdt->base2 = (base >> 16) & 0xFF;
  gdt->access_byte = 0x90 | type;
  gdt->flags = 0xC0 | ((lim >> 28) & 0xF);
  gdt->base3 = (base >> 24) & 0xFF;
}

これらがGDTの要素だと思われる。

GDTは

The Global Descriptor Table (GDT) is a binary data structure specific to the IA-32 and x86-64 architectures. It contains entries telling the CPU about memory segments. A similar Interrupt Descriptor Table exists containing task and interrupt descriptors.

https://wiki.osdev.org/Global_Descriptor_Table

メモリセグメントの情報をCPUに伝えるためのエントリ

IDTは

The Interrupt Descriptor Table (IDT) is a binary data structure specific to the IA-32 and x86-64 architectures. It is the Protected Mode and Long Mode counterpart to the Real Mode Interrupt Vector Table (IVT) telling the CPU where the Interrupt Service Routines (ISR) are located (one per interrupt vector). It is similar to the Global Descriptor Table in structure.

https://wiki.osdev.org/Interrupt_Descriptor_Table

ISRをCPUに伝えるためのエントリ。ISRとは?割り込み発生時に呼ばれるルーチンらしい。ISRはCPUが直接呼ぶのでその位置をあらかじめ伝えておく必要があるということか。

書き込んだGDTは有効化する必要があるっぽい。far jumpとかret trickとかに酔って有効化されるようだ。

far jumpとは?

https://fromnand.hatenadiary.jp/entry/2020/03/07/182250

アセンブラのjump命令の一つで相対でなく絶対位置でジャンプする。

ret trickについては調べても出てこない… おそらくlretqを実行するとfar jumpしたことになるという感じだと思うけど…

昔の記事でlong modeへの移行の話が書かれている

セグメントの設定に関して、

ここらへんの設定は、xv6のbootasm.Sを参考にしています。

ということなのでxv6のコードをみてみよう。そろそろ1日おいた方が良い気がしてきた。

おわる

# やること

  • Growiアプデ & VM to Podman(使ってるとアプデしたくなってくる)
  • xv6のコードとリファレンス?を読む
  • xv6チャンネル遡ってみる(途中)
  • CbC_xv6の現状を把握したい(論文とかコードとかみる感じ)
  • そういえばPerlで書いたUDPソケットのプログラムまとめてなかった
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy