Je développe un OS minuscule à https://github.com/Incarnation-p-lee/excalibur. Récemment, lors de l'activation de la page, j'ai trouvé une différence de sortie lors de l'accès à la mémoire sur 1280 Mo. Supposons un code de suivi:Pourquoi OS image a un comportement différent lors de l'accès à la mémoire autour de 1280 Mo (0x50000000)
static inline void
test_paging(void)
{
uint32 *ptr;
// ptr = (void *)0x800000;
// *ptr = 0xdeadbeaf;
// ptr = (void *)0x4ffffffc;
ptr = (void *)0x50000000;
*ptr = 0xdeadbeaf;
}
[0x00000000] Boot loader magic -> 0x2badb002.
[0x00000000] In Protect Mode.
[0x00000000] Paging disabled.
[0x00000000] OS image start -> 0x00100000
[0x00000000] OS image end -> 0x00109000
[0x00000000] Stack base 0x00100fb4.
[0x00000000] Physical memory lower -> 0000000636 KB.
[0x00000000] Physical memory upper -> 0000261056 KB.
[0x00000000] GDT table initialized.
[0x00000000] IDT table initialized.
[0x00000000] IRQ timer initialized.
[0x00000003] Page enabled from 0x00000000 -> 0x0011c004.
[0x0000000b] Page initialized.
[0x0000000b] In Protect Mode.
[0x0000000b] Paging enabled.
[0x0000000b] Divide by zero at eip -> 0x00101071.
[0x0000000b] Breakpoint at eip -> 0x00101072.
[0x0000000b] Divide by zero at eip -> 0x00101074.
[0x0000000b] Unsupported isq 0000000013.
Assertion: Unsupported ISR
fail.
at function isr_handler_main
in file src/interrupt/isr/isr_handler.c:0000000014
Enter KERNEL PANIC T.T ...
?
Mais quand je veux accéder 0x4ffffffc, il a déclenché erreur de page? Il s'attendait que 0x4ffffffc et 0x50000000 déclenchent une erreur de page dans mon option.
static inline void
test_paging(void)
{
uint32 *ptr;
// ptr = (void *)0x800000;
// *ptr = 0xdeadbeaf;
ptr = (void *)0x4ffffffc;
// ptr = (void *)0x50000000;
*ptr = 0xdeadbeaf;
}
[0x00000000] In Protect Mode.
[0x00000000] Paging disabled.
[0x00000000] OS image start -> 0x00100000
[0x00000000] OS image end -> 0x00109000
[0x00000000] Stack base 0x00100fb4.
[0x00000000] Physical memory lower -> 0000000636 KB.
[0x00000000] Physical memory upper -> 0000261056 KB.
[0x00000000] GDT table initialized.
[0x00000000] IDT table initialized.
[0x00000000] IRQ timer initialized.
[0x00000003] Page enabled from 0x00000000 -> 0x0011c004.
[0x00000006] Page initialized.
[0x00000006] In Protect Mode.
[0x00000006] Paging enabled.
[0x00000006] Divide by zero at eip -> 0x00101071.
[0x00000006] Breakpoint at eip -> 0x00101072.
[0x00000006] Divide by zero at eip -> 0x00101074.
Page is not present.
Page is Read-Only.
Page Fault at address 0x4ffffffc.
Assertion: Page Fault fail.
at function isr_14_paging_fault_handler
in file src/interrupt/isr/isr_handler.c:0000000076
Enter KERNEL PANIC T.T ...
?
Code connexes et définition la structure
void
descriptor_table_gdt_initialize(void)
{
gdt_reg.limit = sizeof(gdt) - 1;
gdt_reg.base = (uint32)&gdt;
gdt_entry_set(0, 0, 0, 0, 0);
gdt_entry_set(1, CODE_SEG_BASE, CODE_SEG_LMT, CODE_SEG_ACC, CODE_SEG_FLAG);
gdt_entry_set(2, DATA_SEG_BASE, DATA_SEG_LMT, DATA_SEG_ACC, DATA_SEG_FLAG);
gdt_entry_set(3, 0, USR_CODE_SEG_LMT, USR_CODE_SEG_ACC, USR_CODE_SEG_FLAG);
gdt_entry_set(4, 0, USR_DATA_SEG_LMT, USR_DATA_SEG_ACC, USR_DATA_SEG_FLAG);
gdt_table_flush((uint32)&gdt_reg);
printf_vga_tk("GDT table initialized.\n");
}
static inline void
gdt_entry_set(uint32 i, uint32 base, uint32 limit, uint16 acc, uint8 flags)
{
kassert(i < GDT_ENTRY_CNT);
gdt[i].base_l = U32_BITS(base, 0, 24);
gdt[i].base_h = (uint8)U32_BITS(base, 24, 8);
gdt[i].lmt_l = (uint16)U32_BITS(limit, 0, 16);
gdt[i].flags.lmt_h = (uint8)U32_BITS(limit, 16, 4);
gdt[i].access.acc = (uint8)U32_BIT(acc, ACC_AC_IDX);
gdt[i].access.rw = (uint8)U32_BIT(acc, ACC_RW_IDX);
gdt[i].access.dc = (uint8)U32_BIT(acc, ACC_DC_IDX);
gdt[i].access.ex = (uint8)U32_BIT(acc, ACC_EX_IDX);
gdt[i].access.dt = (uint8)U32_BIT(acc, ACC_DT_IDX);
gdt[i].access.dpl = (uint8)U32_BITS(acc, ACC_DPL_IDX, ACC_DPL_LEN);
gdt[i].access.p = (uint8)U32_BIT(acc, ACC_P_IDX);
gdt[i].flags.avl = (uint8)U32_BIT(flags, FLAG_A_IDX);
gdt[i].flags.pack = 0;
gdt[i].flags.db = (uint8)U32_BIT(flags, FLAG_DB_IDX);
gdt[i].flags.g = (uint8)U32_BIT(flags, FLAG_G_IDX);
}
#define U32_BIT(x, idx) ((uint32)(x) >> (idx) & 0x1)
#define U32_BITS(x, s, l) (((uint32)(x) >> (s)) & ((0x1 << (l)) - 1))
#define CODE_SEG_BASE 0x0
#define CODE_SEG_LMT 0xffffffff
#define DATA_SEG_BASE 0x0
#define DATA_SEG_LMT 0xffffffff
#define STACK_SEG_BASE 0x300000
#define STACK_SEG_LMT 0xfffff
#define USR_CODE_SEG_LMT 0xffffffff
#define USR_DATA_SEG_LMT 0xffffffff
static s_gdt_entry_t gdt[GDT_ENTRY_CNT];
static s_gdt_register_t gdt_reg;
extern void gdt_table_flush(uint32);
[GLOBAL gdt_table_flush]
gdt_table_flush:
mov eax, [esp + 4]
lgdt [eax]
mov ax, 0x10 ; data segment selector
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x8: .flush ; will change cs register implicitly
.flush:
ret
/*
* Global Descriptor Table Register
* 47 16 15 0
* +----------------------------+-------------------+
* | 32-bit Linear Base Address | 16-bit Table Limit|
* +----------------------------+-------------------+
*/
struct gdt_register {
uint16 limit;
uint32 base;
} __attribute__((packed));
/*
* Descriptor Attribute
* 15 14 13 12 11 8 7 6 5 4 3 2 1 0
* +---+-----+---+-----+----------------+---+-----+----+----+----+----+----+
* | G | D/B | 0 | AVL | Seg limit high | P | DPL | DT | EX | DC | RW | AC |
* +---+-----+---+-----+----------------+---+-----+----+----+----+----+----+
*/
struct gdt_attribute_access {
uint8 acc:1; // Segment has been accessed or not
uint8 rw:1; // Read-only or Read/Write
uint8 dc:1; // Direction for data segment, 0 grow up, 1 grow down or
// Execution for code segment, 0 indicate DPL and more DPL
// 1 indicate only the DPL specify
uint8 ex:1; // Segment can be executed or not.
uint8 dt:1; // Descriptor Type, always 1 for GDT
uint8 dpl:2; // Descriptor privilege level, ring 0-3
uint8 p:1; // Segment is present or not
} __attribute__((packed));
struct gdt_attribute_flags {
uint8 avl:1;
uint8 pack:1;
uint8 db:1; // Operand size, 0 16-bit 1 32-bit
uint8 g:1; // Granularity which defines the limit unit in byte or 4KB
uint8 lmt_h:4; // High 4 bit of limit, bit <16, 19> of limit
} __attribute__((packed));
/*
* Global Descriptor Table Entry (Global Descriptor)
* Each represent a segment in GDT.
* 63 55 51 47 39 15 0
* +-----------+-------+------------+--------+----------+-----------+
* | base high | flags | limit high | access | base low | limit low |
* +-----------+-------+------------+--------+----------+-----------+
* base contains 32-bit
* limit contains 20-bit
*/
struct gdt_entry {
uint16 lmt_l;
uint32 base_l:24;
struct gdt_attribute_access access;
struct gdt_attribute_flags flags;
uint8 base_h;
} __attribute__((packed));
Bochs config
# configuration file generated by Bochs
plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1
config_interface: win32config
display_library: win32
memory: host=256, guest=256
romimage: file="C:\Program Files (x86)\Bochs-2.6.8/BIOS-bochs-latest"
vgaromimage: file="C:\Program Files (x86)\Bochs-2.6.8/VGABIOS-lgpl-latest"
boot: floppy
floppy_bootsig_check: disabled=0
floppya: type=1_44, 1_44="C:\Users\pli\Desktop\workspace\bochs\floppy.img", status=inserted, write_protected=0
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=none
ata0-slave: type=none
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=none
ata1-slave: type=none
ata2: enabled=0
ata3: enabled=0
pci: enabled=1, chipset=i440fx
vga: extension=vbe, update_freq=5, realtime=1
cpu: count=1, ips=1000000, model=bx_generic, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU "
cpuid: mmx=1, apic=xapic, simd=sse2, sse4a=0, misaligned_sse=0, sep=1, movbe=0, adx=0
cpuid: aes=0, sha=0, xsave=0, xsaveopt=0, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0
cpuid: smep=0, smap=0, mwait=1, vmx=1
print_timestamps: enabled=0
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=realtime, time0=local, rtc_sync=0
# no cmosimage
# no loader
log: bochsout.txt
logprefix: %t%e%d
debug: action=ignore
info: action=report
error: action=report
panic: action=ask
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
mouse: type=ps2, enabled=0, toggle=ctrl+mbutton
sound: waveoutdrv=win, waveout=none, waveindrv=win, wavein=none, midioutdrv=win, midiout=none
speaker: enabled=1, mode=sound
parport1: enabled=1, file=none
parport2: enabled=0
com1: enabled=1, mode=null
com2: enabled=0
com3: enabled=0
com4: enabled=0
Vous semblez avoir l'interruption 13 (défaut de protection générale) au lieu de l'interruption 14 (erreur de page). Je suppose que c'est quelque chose à voir avec la façon dont vous avez configuré les descripteurs de segment, mais sans voir votre code, je ne peux pas le dire avec certitude. Dans tous les cas, le manuel d'architecture x86 vous expliquera en détails douloureux exactement quand vous obtenez une interruption par rapport à l'autre; Si vous écrivez un système d'exploitation à partir de zéro, vous devriez connaître le manuel d'architecture par cœur. – zwol
Ne postez pas d'images de texte! – Olaf
Je vais mettre à jour plus d'informations plus tard, ainsi que de remplacer l'image. Merci à tous, et je dois prendre soin de mon petit bébé pour l'instant et poster plus de code plus tard. MERCI ENCORE! –