Update some broken anchor links (#1444)

This commit is contained in:
Philipp Oppermann
2025-12-08 17:31:52 +01:00
committed by GitHub
parent 86c36479cf
commit 211f460251
56 changed files with 387 additions and 387 deletions

View File

@@ -132,7 +132,7 @@ type HandlerFunc = extern "x86-interrupt" fn(_: InterruptStackFrame);
Es un [alias de tipo] para un tipo de `extern "x86-interrupt" fn`. La palabra clave `extern` define una función con una [convención de llamada foránea] y se utiliza a menudo para comunicarse con código C (`extern "C" fn`). Pero, ¿cuál es la convención de llamada `x86-interrupt`?
[alias de tipo]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases
[alias de tipo]: https://doc.rust-lang.org/book/ch20-03-advanced-types.html#creating-type-synonyms-with-type-aliases
[convención de llamada foránea]: https://doc.rust-lang.org/nomicon/ffi.html#foreign-calling-conventions
## La convención de llamada de interrupción
@@ -329,7 +329,7 @@ pub fn init_idt() {
Sin embargo, hay un problema: las estáticas son inmutables, por lo que no podemos modificar la entrada de punto de interrupción desde nuestra función `init`. Podríamos resolver este problema utilizando un [`static mut`]:
[`static mut`]: https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
[`static mut`]: https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
```rust
static mut IDT: InterruptDescriptorTable = InterruptDescriptorTable::new();

View File

@@ -47,28 +47,28 @@ rtl = true
### جدول توصیف کننده وقفه
برای گرفتن و رسیدگی به استثنا‌ها ، باید اصطلاحاً _جدول توصیفگر وقفه_ (IDT) را تنظیم کنیم. در این جدول می توانیم برای هر استثنا پردازنده یک عملکرد تابع کننده مشخص کنیم. سخت افزار به طور مستقیم از این جدول استفاده می کند ، بنابراین باید از یک قالب از پیش تعریف شده پیروی کنیم. هر ورودی جدول باید ساختار 16 بایتی زیر را داشته باشد:
Type| Name | Description
----|--------------------------|-----------------------------------
u16 | Function Pointer [0:15] | The lower bits of the pointer to the handler function.
u16 | GDT selector | Selector of a code segment in the [global descriptor table].
u16 | Options | (see below)
u16 | Function Pointer [16:31] | The middle bits of the pointer to the handler function.
u32 | Function Pointer [32:63] | The remaining bits of the pointer to the handler function.
u32 | Reserved |
| Type | Name | Description |
| ---- | ------------------------ | ------------------------------------------------------------ |
| u16 | Function Pointer [0:15] | The lower bits of the pointer to the handler function. |
| u16 | GDT selector | Selector of a code segment in the [global descriptor table]. |
| u16 | Options | (see below) |
| u16 | Function Pointer [16:31] | The middle bits of the pointer to the handler function. |
| u32 | Function Pointer [32:63] | The remaining bits of the pointer to the handler function. |
| u32 | Reserved |
[global descriptor table]: https://en.wikipedia.org/wiki/Global_Descriptor_Table
قسمت گزینه ها (Options) دارای قالب زیر است:
Bits | Name | Description
------|-----------------------------------|-----------------------------------
0-2 | Interrupt Stack Table Index | 0: Don't switch stacks, 1-7: Switch to the n-th stack in the Interrupt Stack Table when this handler is called.
3-7 | Reserved |
8 | 0: Interrupt Gate, 1: Trap Gate | If this bit is 0, interrupts are disabled when this handler is called.
9-11 | must be one |
12 | must be zero |
1314 | Descriptor Privilege Level (DPL) | The minimal privilege level required for calling this handler.
15 | Present |
| Bits | Name | Description |
| ----- | -------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| 0-2 | Interrupt Stack Table Index | 0: Don't switch stacks, 1-7: Switch to the n-th stack in the Interrupt Stack Table when this handler is called. |
| 3-7 | Reserved |
| 8 | 0: Interrupt Gate, 1: Trap Gate | If this bit is 0, interrupts are disabled when this handler is called. |
| 9-11 | must be one |
| 12 | must be zero |
| 1314 | Descriptor Privilege Level (DPL) | The minimal privilege level required for calling this handler. |
| 15 | Present |
هر استثنا دارای یک اندیس از پیش تعریف شده در IDT است. به عنوان مثال استثنا کد نامعتبر دارای اندیس 6 و استثنا خطای صفحه دارای اندیس 14 است. بنابراین ، سخت افزار می تواند به طور خودکار عنصر مربوطه را برای هر استثنا بارگذاری کند. [جدول استثناها][exceptions] در ویکی OSDev ، اندیس های IDT کلیه استثناها را در ستون “Vector nr.” نشان داده است.
@@ -134,7 +134,7 @@ type HandlerFunc = extern "x86-interrupt" fn(_: InterruptStackFrame);
این یک [نوع مستعار(type alias)] برای نوع "`extern "x86-interrupt" fn` است. کلمه کلیدی `extern` تابعی را با یک [قرارداد فراخوانی خارجی] تعریف می کند و اغلب برای برقراری ارتباط با کد C استفاده می شود(`extern "C" fn`) . اما قرارداد فراخوانی `x86-interrupt` چیست؟
[نوع مستعار(type alias)]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases
[نوع مستعار(type alias)]: https://doc.rust-lang.org/book/ch20-03-advanced-types.html#creating-type-synonyms-with-type-aliases
[قرارداد فراخوانی خارجی]: https://doc.rust-lang.org/nomicon/ffi.html#foreign-calling-conventions
## قرارداد فراخوانی وقفه
@@ -164,10 +164,10 @@ type HandlerFunc = extern "x86-interrupt" fn(_: InterruptStackFrame);
در x86_64 ، قرارداد فراخوانی C ثبات‌های محفوظ شده و تغییرشونده زیر را مشخص می کند:
preserved registers | scratch registers
---|---
`rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11`
_callee-saved_ | _caller-saved_
| preserved registers | scratch registers |
| ----------------------------------------------- | ----------------------------------------------------------- |
| `rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11` |
| _callee-saved_ | _caller-saved_ |
کامپایلر این قوانین را می داند ، بنابراین کد را متناسب با آن تولید می کند. به عنوان مثال ، بیشتر توابع با `push rbp` شروع می شوند که پشتیبان گیری از`rbp` روی پشته است (زیرا این یک ثبات _caller-saved_).
@@ -330,7 +330,7 @@ pub fn init_idt() {
با این وجود، یک مشکل وجود دارد: استاتیک‌ها تغییرناپذیر هستند، پس نمی توانیم ورودی بریک‌پوینت را از تابع `init` تغییر دهیم. می توانیم این مشکل را با استفاده از [`static mut`] حل کنیم:
[`static mut`]: https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
[`static mut`]: https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
```rust
static mut IDT: InterruptDescriptorTable = InterruptDescriptorTable::new();

View File

@@ -46,28 +46,28 @@ x86には20種類のCPU例外があります。中でも重要なものは
### 割り込み記述子表
例外を捕捉し処理するためには、いわゆる割り込み記述子表 (Interrupt Descriptor Table, IDT) を設定しないといけません。この表にそれぞれのCPU例外に対するハンドラ関数を指定することができます。ハードウェアはこの表を直接使うので、決められたフォーマットに従わないといけません。それぞれのエントリは以下の16バイトの構造を持たなければなりません
型 | 名前 | 説明
----|--------------------------|-----------------------------------
u16 | 関数ポインタ [0:15] | ハンドラ関数へのポインタの下位ビット。
u16 | GDTセレクタ | [大域記述子表 (Global Descriptor Table)][global descriptor table] におけるコードセグメントのセレクタ。
u16 | オプション | (下を参照)
u16 | 関数ポインタ [16:31] | ハンドラ関数へのポインタの中位ビット。
u32 | 関数ポインタ [32:63] | ハンドラ関数へのポインタの上位ビット。
u32 | 予約済 |
| 型 | 名前 | 説明 |
| --- | ------------------------ | ------------------------------------------------------------------------------------------------------ |
| u16 | 関数ポインタ [0:15] | ハンドラ関数へのポインタの下位ビット。 |
| u16 | GDTセレクタ | [大域記述子表 (Global Descriptor Table)][global descriptor table] におけるコードセグメントのセレクタ。 |
| u16 | オプション | (下を参照) |
| u16 | 関数ポインタ [16:31] | ハンドラ関数へのポインタの中位ビット。 |
| u32 | 関数ポインタ [32:63] | ハンドラ関数へのポインタの上位ビット。 |
| u32 | 予約済 |
[global descriptor table]: https://en.wikipedia.org/wiki/Global_Descriptor_Table
オプション部は以下のフォーマットになっています:
ビット | 名前 | 説明
--------|------------------------------------------------------------------------------------------------|-------------------------------------
0-2 | 割り込みスタックテーブルインデックス | 0ならスタックを変えない。1から7なら、ハンドラが呼ばれたとき、割り込みスタック表のその数字のスタックに変える。
3-7 | 予約済 |
8 | 0: 割り込みゲート、1: トラップゲート | 0なら、このハンドラが呼ばれたとき割り込みは無効化される。
9-11 | 1にしておかないといけない |
12 | 0にしておかないといけない |
1314 | <ruby>記述子の特権レベル<rp> (</rp><rt>Descriptor Privilege Level</rt><rp>) </rp></ruby> (DPL) | このハンドラを呼ぶ際に必要になる最低限の特権レベル。
15 | Present |
| ビット | 名前 | 説明 |
| ------ | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| 0-2 | 割り込みスタックテーブルインデックス | 0ならスタックを変えない。1から7なら、ハンドラが呼ばれたとき、割り込みスタック表のその数字のスタックに変える。 |
| 3-7 | 予約済 |
| 8 | 0: 割り込みゲート、1: トラップゲート | 0なら、このハンドラが呼ばれたとき割り込みは無効化される。 |
| 9-11 | 1にしておかないといけない |
| 12 | 0にしておかないといけない |
| 1314 | <ruby>記述子の特権レベル<rp> (</rp><rt>Descriptor Privilege Level</rt><rp>) </rp></ruby> (DPL) | このハンドラを呼ぶ際に必要になる最低限の特権レベル。 |
| 15 | Present |
それぞれの例外がIDTの何番目に対応するかは事前に定義されています。例えば、「無効な命令コード」の例外は6番目で、「ページフォルト」例外は14番目です。これにより、ハードウェアがそれぞれの例外に対応するIDTの設定を特に設定の必要なく自動的に読み出せるというわけです。OSDev wikiの[「例外表」][exceptions]の "Vector nr." 列に、すべての例外についてIDTの何番目かが記されています。
@@ -132,7 +132,7 @@ type HandlerFunc = extern "x86-interrupt" fn(_: InterruptStackFrame);
これは、`extern "x86-interrupt" fn`型への[型エイリアス][type alias]です。`extern`は[外部呼び出し規約][foreign calling convention]に従う関数を定義するのに使われ、おもにC言語のコードと連携したいときに使われます (`extern "C" fn`) 。しかし、`x86-interrupt`呼び出し規約とは何なのでしょう?
[type alias]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases
[type alias]: https://doc.rust-lang.org/book/ch20-03-advanced-types.html#creating-type-synonyms-with-type-aliases
[foreign calling convention]: https://doc.rust-lang.org/nomicon/ffi.html#foreign-calling-conventions
## 例外の呼び出し規約
@@ -162,10 +162,10 @@ preservedレジスタの値は関数呼び出しの前後で変化してはい
x86_64においては、C言語の呼び出し規約は以下のpreservedレジスタとscratchレジスタを指定します
preservedレジスタ | scratchレジスタ
--- | ---
`rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11`
_callee-saved_ | _caller-saved_
| preservedレジスタ | scratchレジスタ |
| ----------------------------------------------- | ----------------------------------------------------------- |
| `rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11` |
| _callee-saved_ | _caller-saved_ |
コンパイラはこれらのルールを知っているので、それにしたがってコードを生成します。例えば、ほとんどの関数は`push rbp`から始まるのですが、これは`rbp`をスタックにバックアップしているのです(`rbp`はcallee-savedなレジスタであるため
@@ -329,7 +329,7 @@ pub fn init_idt() {
しかし、問題が発生しますstaticは<ruby>不変<rp> (</rp><rt>イミュータブル</rt><rp>) </rp></ruby>なので、`init`関数でエントリを変更することができません。これは[`static mut`]を使って解決できそうです:
[`static mut`]: https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
[`static mut`]: https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
```rust
static mut IDT: InterruptDescriptorTable = InterruptDescriptorTable::new();

View File

@@ -49,14 +49,14 @@ x86 아키텍처에는 20가지 정도의 CPU 예외가 존재합니다. 그 중
예외 발생을 포착하고 대응할 수 있으려면 _인터럽트 서술자 테이블 (Interrupt Descriptor Table; IDT)_ 이 필요합니다.
이 테이블을 통해 우리는 각각의 CPU 예외를 어떤 예외 처리 함수가 처리할지 지정합니다. 하드웨어에서 이 테이블을 직접 사용하므로 테이블의 형식은 정해진 표준에 따라야 합니다. 테이블의 각 엔트리는 아래와 같은 16 바이트 구조를 따릅니다:
| 타입 | 이름 | 설명 |
| ---- | ------------------------ | ------------------------------------------------------------------------------------------------------------- |
| u16 | Function Pointer [0:15] | 예외 처리 함수에 대한 64비트 포인터의 하위 16비트 |
| 타입 | 이름 | 설명 |
| ---- | ------------------------ | ------------------------------------------------------------------------------------------------------- |
| u16 | Function Pointer [0:15] | 예외 처리 함수에 대한 64비트 포인터의 하위 16비트 |
| u16 | GDT selector | [전역 서술자 테이블 (global descriptor table)][global descriptor table]에서 코드 세그먼트를 선택하는 값 |
| u16 | Options | (표 아래의 설명 참조) |
| u16 | Function Pointer [16:31] | 예외 처리 함수에 대한 64비트 포인터의 2번째 하위 16비트 |
| u32 | Function Pointer [32:63] | 예외 처리 함수에 대한 64비트 포인터의 상위 32비트 |
| u32 | Reserved | 사용 보류 중인 영역 |
| u16 | Options | (표 아래의 설명 참조) |
| u16 | Function Pointer [16:31] | 예외 처리 함수에 대한 64비트 포인터의 2번째 하위 16비트 |
| u32 | Function Pointer [32:63] | 예외 처리 함수에 대한 64비트 포인터의 상위 32비트 |
| u32 | Reserved | 사용 보류 중인 영역 |
[global descriptor table]: https://en.wikipedia.org/wiki/Global_Descriptor_Table
@@ -135,7 +135,7 @@ type HandlerFunc = extern "x86-interrupt" fn(_: InterruptStackFrame);
`HandlerFunc`는 함수 타입 `extern "x86-interrupt" fn`의 [타입 별칭][type alias]입니다. `extern` 키워드는 [외부 함수 호출 규약 (foreign calling convention)][foreign calling convention]을 사용하는 함수를 정의할 때 쓰이는데, 주로 C 함수와 상호작용하는 경우에 쓰입니다 (`extern "C" fn`). `x86-interrupt` 함수 호출 규약은 무엇일까요?
[type alias]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases
[type alias]: https://doc.rust-lang.org/book/ch20-03-advanced-types.html#creating-type-synonyms-with-type-aliases
[foreign calling convention]: https://doc.rust-lang.org/nomicon/ffi.html#foreign-calling-conventions
## 인터럽트 호출 규약
@@ -334,7 +334,7 @@ pub fn init_idt() {
문제는 static 변수의 값은 변경할 수가 없어서, `init` 함수 실행 시 breakpoint 예외에 대응하는 IDT 엔트리를 수정할 수 없습니다.
대신 `IDT`를 [`static mut`] 변수에 저장해보겠습니다:
[`static mut`]: https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
[`static mut`]: https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
```rust
static mut IDT: InterruptDescriptorTable = InterruptDescriptorTable::new();

View File

@@ -43,28 +43,28 @@ For the full list of exceptions, check out the [OSDev wiki][exceptions].
### The Interrupt Descriptor Table
In order to catch and handle exceptions, we have to set up a so-called _Interrupt Descriptor Table_ (IDT). In this table, we can specify a handler function for each CPU exception. The hardware uses this table directly, so we need to follow a predefined format. Each entry must have the following 16-byte structure:
Type| Name | Description
----|--------------------------|-----------------------------------
u16 | Function Pointer [0:15] | The lower bits of the pointer to the handler function.
u16 | GDT selector | Selector of a code segment in the [global descriptor table].
u16 | Options | (see below)
u16 | Function Pointer [16:31] | The middle bits of the pointer to the handler function.
u32 | Function Pointer [32:63] | The remaining bits of the pointer to the handler function.
u32 | Reserved |
| Type | Name | Description |
| ---- | ------------------------ | ------------------------------------------------------------ |
| u16 | Function Pointer [0:15] | The lower bits of the pointer to the handler function. |
| u16 | GDT selector | Selector of a code segment in the [global descriptor table]. |
| u16 | Options | (see below) |
| u16 | Function Pointer [16:31] | The middle bits of the pointer to the handler function. |
| u32 | Function Pointer [32:63] | The remaining bits of the pointer to the handler function. |
| u32 | Reserved |
[global descriptor table]: https://en.wikipedia.org/wiki/Global_Descriptor_Table
The options field has the following format:
Bits | Name | Description
------|-----------------------------------|-----------------------------------
0-2 | Interrupt Stack Table Index | 0: Don't switch stacks, 1-7: Switch to the n-th stack in the Interrupt Stack Table when this handler is called.
3-7 | Reserved |
8 | 0: Interrupt Gate, 1: Trap Gate | If this bit is 0, interrupts are disabled when this handler is called.
9-11 | must be one |
12 | must be zero |
1314 | Descriptor Privilege Level (DPL) | The minimal privilege level required for calling this handler.
15 | Present |
| Bits | Name | Description |
| ----- | -------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| 0-2 | Interrupt Stack Table Index | 0: Don't switch stacks, 1-7: Switch to the n-th stack in the Interrupt Stack Table when this handler is called. |
| 3-7 | Reserved |
| 8 | 0: Interrupt Gate, 1: Trap Gate | If this bit is 0, interrupts are disabled when this handler is called. |
| 9-11 | must be one |
| 12 | must be zero |
| 1314 | Descriptor Privilege Level (DPL) | The minimal privilege level required for calling this handler. |
| 15 | Present |
Each exception has a predefined IDT index. For example, the invalid opcode exception has table index 6 and the page fault exception has table index 14. Thus, the hardware can automatically load the corresponding IDT entry for each exception. The [Exception Table][exceptions] in the OSDev wiki shows the IDT indexes of all exceptions in the “Vector nr.” column.
@@ -129,7 +129,7 @@ type HandlerFunc = extern "x86-interrupt" fn(_: InterruptStackFrame);
It's a [type alias] for an `extern "x86-interrupt" fn` type. The `extern` keyword defines a function with a [foreign calling convention] and is often used to communicate with C code (`extern "C" fn`). But what is the `x86-interrupt` calling convention?
[type alias]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases
[type alias]: https://doc.rust-lang.org/book/ch20-03-advanced-types.html#creating-type-synonyms-with-type-aliases
[foreign calling convention]: https://doc.rust-lang.org/nomicon/ffi.html#foreign-calling-conventions
## The Interrupt Calling Convention
@@ -159,10 +159,10 @@ In contrast, a called function is allowed to overwrite _scratch_ registers witho
On x86_64, the C calling convention specifies the following preserved and scratch registers:
preserved registers | scratch registers
---|---
`rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11`
_callee-saved_ | _caller-saved_
| preserved registers | scratch registers |
| ----------------------------------------------- | ----------------------------------------------------------- |
| `rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11` |
| _callee-saved_ | _caller-saved_ |
The compiler knows these rules, so it generates the code accordingly. For example, most functions begin with a `push rbp`, which backups `rbp` on the stack (because it's a callee-saved register).
@@ -327,7 +327,7 @@ pub fn init_idt() {
However, there is a problem: Statics are immutable, so we can't modify the breakpoint entry from our `init` function. We could solve this problem by using a [`static mut`]:
[`static mut`]: https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
[`static mut`]: https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
```rust
static mut IDT: InterruptDescriptorTable = InterruptDescriptorTable::new();

View File

@@ -48,28 +48,28 @@ Para a lista completa de exceções, consulte a [wiki do OSDev][exceptions].
### A Tabela de Descritores de Interrupção
Para capturar e manipular exceções, precisamos configurar uma chamada _Tabela de Descritores de Interrupção_ (IDT - Interrupt Descriptor Table). Nesta tabela, podemos especificar uma função manipuladora para cada exceção de CPU. O hardware usa esta tabela diretamente, então precisamos seguir um formato predefinido. Cada entrada deve ter a seguinte estrutura de 16 bytes:
Tipo| Nome | Descrição
----|--------------------------|-----------------------------------
u16 | Function Pointer [0:15] | Os bits inferiores do ponteiro para a função manipuladora.
u16 | GDT selector | Seletor de um segmento de código na [tabela de descritores globais].
u16 | Options | (veja abaixo)
u16 | Function Pointer [16:31] | Os bits do meio do ponteiro para a função manipuladora.
u32 | Function Pointer [32:63] | Os bits restantes do ponteiro para a função manipuladora.
u32 | Reserved |
| Tipo | Nome | Descrição |
| ---- | ------------------------ | -------------------------------------------------------------------- |
| u16 | Function Pointer [0:15] | Os bits inferiores do ponteiro para a função manipuladora. |
| u16 | GDT selector | Seletor de um segmento de código na [tabela de descritores globais]. |
| u16 | Options | (veja abaixo) |
| u16 | Function Pointer [16:31] | Os bits do meio do ponteiro para a função manipuladora. |
| u32 | Function Pointer [32:63] | Os bits restantes do ponteiro para a função manipuladora. |
| u32 | Reserved |
[tabela de descritores globais]: https://en.wikipedia.org/wiki/Global_Descriptor_Table
O campo options tem o seguinte formato:
Bits | Nome | Descrição
------|-----------------------------------|-----------------------------------
0-2 | Interrupt Stack Table Index | 0: Não troca stacks, 1-7: Troca para a n-ésima stack na Interrupt Stack Table quando este manipulador é chamado.
3-7 | Reserved |
8 | 0: Interrupt Gate, 1: Trap Gate | Se este bit é 0, as interrupções são desativadas quando este manipulador é chamado.
9-11 | must be one |
12 | must be zero |
1314 | Descriptor Privilege Level (DPL) | O nível mínimo de privilégio necessário para chamar este manipulador.
15 | Present |
| Bits | Nome | Descrição |
| ----- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 0-2 | Interrupt Stack Table Index | 0: Não troca stacks, 1-7: Troca para a n-ésima stack na Interrupt Stack Table quando este manipulador é chamado. |
| 3-7 | Reserved |
| 8 | 0: Interrupt Gate, 1: Trap Gate | Se este bit é 0, as interrupções são desativadas quando este manipulador é chamado. |
| 9-11 | must be one |
| 12 | must be zero |
| 1314 | Descriptor Privilege Level (DPL) | O nível mínimo de privilégio necessário para chamar este manipulador. |
| 15 | Present |
Cada exceção tem um índice predefinido na IDT. Por exemplo, a exceção invalid opcode tem índice de tabela 6 e a exceção page fault tem índice de tabela 14. Assim, o hardware pode automaticamente carregar a entrada IDT correspondente para cada exceção. A [Tabela de Exceções][exceptions] na wiki do OSDev mostra os índices IDT de todas as exceções na coluna "Vector nr.".
@@ -134,7 +134,7 @@ type HandlerFunc = extern "x86-interrupt" fn(_: InterruptStackFrame);
É um [type alias] para um tipo `extern "x86-interrupt" fn`. A palavra-chave `extern` define uma função com uma [convenção de chamada estrangeira] e é frequentemente usada para se comunicar com código C (`extern "C" fn`). Mas o que é a convenção de chamada `x86-interrupt`?
[type alias]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases
[type alias]: https://doc.rust-lang.org/book/ch20-03-advanced-types.html#creating-type-synonyms-with-type-aliases
[convenção de chamada estrangeira]: https://doc.rust-lang.org/nomicon/ffi.html#foreign-calling-conventions
## A Convenção de Chamada de Interrupção
@@ -164,10 +164,10 @@ Em contraste, uma função chamada tem permissão para sobrescrever registradore
No x86_64, a convenção de chamada C especifica os seguintes registradores preservados e scratch:
registradores preservados | registradores scratch
---|---
`rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11`
_callee-saved_ | _caller-saved_
| registradores preservados | registradores scratch |
| ----------------------------------------------- | ----------------------------------------------------------- |
| `rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11` |
| _callee-saved_ | _caller-saved_ |
O compilador conhece essas regras, então gera o código de acordo. Por exemplo, a maioria das funções começa com um `push rbp`, que faz backup de `rbp` na pilha (porque é um registrador callee-saved).
@@ -471,4 +471,4 @@ A convenção de chamada `x86-interrupt` e o tipo [`InterruptDescriptorTable`] t
Capturamos com sucesso nossa primeira exceção e retornamos dela! O próximo passo é garantir que capturemos todas as exceções porque uma exceção não capturada causa um [triple fault] fatal, que leva a uma redefinição do sistema. A próxima postagem explica como podemos evitar isso capturando corretamente [double faults].
[triple fault]: https://wiki.osdev.org/Triple_Fault
[double faults]: https://wiki.osdev.org/Double_Fault#Double_Fault
[double faults]: https://wiki.osdev.org/Double_Fault#Double_Fault

View File

@@ -134,7 +134,7 @@ type HandlerFunc = extern "x86-interrupt" fn(_: InterruptStackFrame);
这是一个针对 `extern "x86-interrupt" fn` 类型的 [类型别名][type alias]。`extern` 关键字使用 [外部调用约定][foreign calling convention] 定义了一个函数这种定义方式多用于和C语言代码通信`extern "C" fn`),那么这里的外部调用约定又究竟调用了哪些东西?
[type alias]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases
[type alias]: https://doc.rust-lang.org/book/ch20-03-advanced-types.html#creating-type-synonyms-with-type-aliases
[foreign calling convention]: https://doc.rust-lang.org/nomicon/ffi.html#foreign-calling-conventions
## 中断调用约定
@@ -331,7 +331,7 @@ pub fn init_idt() {
然而这样就会引入一个新问题:静态变量是不可修改的,这样我们就无法在 `init` 函数中修改里面的数据了,所以需要把变量类型修改为 [`static mut`]
[`static mut`]: https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
[`static mut`]: https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
```rust
static mut IDT: InterruptDescriptorTable = InterruptDescriptorTable::new();