gpt4 book ai didi

C 指针未设置

转载 作者:太空狗 更新时间:2023-10-29 16:39:08 24 4
gpt4 key购买 nike

我正在创建一种玩具操作系统,我正在尝试设置分页。引导加载程序首先将内核映射到较高的一半,然后我尝试设置一个新的页面目录。

我有一些这样定义的结构:

typedef struct pd_entry pd_entry_t;
struct pd_entry
{
uint32_t present : 1;
uint32_t writable : 1;
uint32_t user : 1;
uint32_t writethru : 1;
uint32_t nocache : 1;
uint32_t accessed : 1;
uint32_t _reserved : 1;
uint32_t size_4mb : 1;
uint32_t global : 1;
uint32_t available : 3;
uint32_t frame : 20;
}__attribute__((packed));

typedef struct pt_entry pt_entry_t;
struct pt_entry
{
uint32_t present : 1;
uint32_t writable : 1;
uint32_t user : 1;
uint32_t writethru : 1;
uint32_t nocache : 1;
uint32_t accessed : 1;
uint32_t dirty : 1;
uint32_t attr_index : 1;
uint32_t global : 1;
uint32_t available : 3;
uint32_t frame : 20;
} __attribute__((packed));

typedef struct page_dir page_dir_t;
struct page_dir
{
pd_entry_t entries[TABLES_PER_DIR];
};

typedef struct page_table page_table_t;
struct page_table
{
pt_entry_t entries[PAGES_PER_TABLE];
};

我使用这段代码来设置条目:

// I store the page directory pointer in the last directory entry
uint32_t map_quick(uint32_t addr)
{
GET_PTE(QUICKMAP_ADDR)->frame = PAGE_ALIGN(addr) >> 12; // QUICKMAP_ADDR is 0xC0000000
paging_flush_tlb_entry(QUICKMAP_ADDR); // asm volatile ("invlpg (%0)" :: "r"(addr));
return QUICKMAP_ADDR;
}

pd_entry_t* get_dir_entry(page_dir_t *dir, uint32_t virt)
{
dir = (page_dir_t *)map_quick((uint32_t)dir);
return &dir->entries[PAGE_DIR_INDEX(virt)];
}

void set_dir_entry(page_dir_t *dir, uint32_t virt, page_table_t *pt)
{
pd_entry_t *pde = get_dir_entry(dir, virt);

pde->present = 1;
pde->writable = 1;
pde->user = 0;
pde->writethru = 0;
pde->nocache = 0;
pde->accessed = 0;
pde->size_4mb = 0;
pde->global = 0;
pde->frame = (uint32_t)pt >> 12;
kprintf("0x%x:0x%x ", (uint32_t)pt >> 12, pde->frame); // Just a 'printf' clone
}

但是,当调用 set_dir_entry 时,kprintf 打印 0xA0:0x0。我不明白为什么 pde->frame 没有设置?我没有收到任何页面错误或异常,无论我将其设置为什么,目录条目始终等于 0

编辑:这是 kprintf 的代码:

size_t kprintf(const char *str, ...)
{
if (!str) return 0;

va_list args;
va_start(args, str);

unsigned int i;
for (i = 0; i < strlen(str); i++)
{
if (str[i] == '%')
{
switch (str[i+1])
{
case 'c':
{
char c = va_arg(args, char);
kputc(c);
i++;
break;
}
case 's':
{
char *s = va_arg(args, char*);
kputs(s);
i++;
break;
}
case 'd':
case 'i':
{
int c = va_arg(args, int);
char s[32] = {0};
itoa_s(c, s, 10);
kputs(s);
i++;
break;
}
case 'X':
case 'x':
{
int c = va_arg(args, int);
char s[32] = {0};
itoa_s(c, s, 16);
kputs(s);
i++;
break;
}
}
}
else
{
kputc(str[i]);
}
}

va_end(args);
return (size_t)i;
}

void kputc(unsigned char c)
{
uint16_t attr = color << 8;

if (c == 0x8 && posx)
posx--;
else if (c == 0x9)
posx = (posx + 8) & ~(8-1);
else if (c == '\r')
posx = 0;
else if (c == '\n')
{
posx = 0;
posy++;
}
else if (c >= ' ')
{
uint16_t *loc = videomem + (posy*80 + posx);
*loc = c | attr;
posx++;
}

if (posx >= 80)
{
posx = 0;
posy++;
}
if (posy >= 25)
kscroll();
}

void kputs(const char *str)
{
if (!str) return;

unsigned int i;
for (i = 0; i < strlen(str); i++)
kputc(str[i]);
}

编辑 2:我不知道这是否有用,而且我真的不喜欢只是转储大量代码供人们阅读,但这是整个分页代码。所有不属于此代码的函数调用都可以独立运行。

虚拟.h

#ifndef _VIRTUAL_H_
#define _VIRTUAL_H_

#include <x86/paging.h>
#include <stdbool.h>

#define VIRTUAL_TO_PHYSICAL(x) ((uint32_t)(x) - 0xC0001000 + 0x00101000)
#define PHYSICAL_TO_VIRTUAL(x) ((uint32_t)(x) + 0xC0001000 - 0x00101000)

#define KERNEL_CODE_VADDRESS 0xC0001000
#define KERNEL_HEAP_VADDRESS 0xD0000000

void virtual_init();

void virtual_create_dir(page_dir_t **dir);
void virtual_destroy_dir(page_dir_t *dir);
void virtual_set_dir(page_dir_t *dir);

void virtual_map_page(page_dir_t *dir, uint32_t phys, uint32_t virt, bool present);
void virtual_map_kernel(page_dir_t *dir);

#endif

虚拟.c

#include <system/memory/physical.h>
#include <x86/idt.h>
#include <utils/kernio.h>
#include <utils/kernpanic.h>
#include <string.h>
#include "virtual.h"

#define QUICKMAP_ADDR 0xC0000000

#define GET_PDE(x) ((pd_entry_t *)(0xFFFFF000 + ((x) >> 22) * 4))
#define GET_PTE(x) ((pt_entry_t *)(0xFFC00000 + ((x) >> 12) * 4))

extern uint32_t __kernel_start, __kernel_end;

page_dir_t *kern_dir;

pd_entry_t* get_dir_entry(page_dir_t *dir, uint32_t virt);
void set_dir_entry(page_dir_t *dir, uint32_t virt, page_table_t *pt);
pt_entry_t* get_table_entry(page_dir_t *dir, uint32_t virt);
void set_table_entry(page_dir_t *dir, uint32_t phys, uint32_t virt, bool present);

uint32_t map_quick(uint32_t addr);

void interrupt page_fault(registers_t *regs);

void virtual_init()
{
int_enable(14, page_fault);

virtual_create_dir(&kern_dir);

uint32_t phys, virt;
for (phys = 0; phys < 0x400000; phys += PAGE_SIZE)
virtual_map_page(kern_dir, phys, phys, true);

phys = VIRTUAL_TO_PHYSICAL(&__kernel_start);
virt = (uint32_t)&__kernel_start;

uint32_t end = VIRTUAL_TO_PHYSICAL(&__kernel_end) + physical_get_bitmap_size();
for (; phys < end; phys += PAGE_SIZE, virt += PAGE_SIZE)
virtual_map_page(kern_dir, phys, virt, true);

virtual_map_page(kern_dir, 0x0, QUICKMAP_ADDR, true);

virtual_set_dir(kern_dir);
}

void virtual_create_dir(page_dir_t **dir)
{
*dir = (page_dir_t *)physical_alloc_block();
page_dir_t *virt_dir = (page_dir_t *)map_quick((uint32_t)*dir);
memset(virt_dir, 0, sizeof(page_dir_t));

pd_entry_t *last_pde = &virt_dir->entries[TABLES_PER_DIR - 1];
last_pde->present = 1;
last_pde->writable = 1;
last_pde->frame = (uint32_t)*dir >> 12;
}

void virtual_destroy_dir(page_dir_t *dir)
{
page_dir_t *virt_dir = (page_dir_t *)map_quick((uint32_t)dir);

unsigned int i, j;
for (i = 1; i < KERNEL_CODE_VADDRESS / (PAGE_SIZE * TABLES_PER_DIR); i++)
{
pd_entry_t *pde = &virt_dir->entries[i];
page_table_t *table = (page_table_t *)(pde->frame << 12);

if (table != NULL && pde->present)
{
page_table_t *virt_table = (page_table_t *)map_quick((uint32_t)table);
for (j = 0; j < PAGES_PER_TABLE; j++)
{
pt_entry_t *pte = &virt_table->entries[j];
uint32_t phys = pte->frame << 12;
if (phys != NULL && pte->present)
physical_free_block((void *)phys);
}

physical_free_block(table);
}
}

physical_free_block(dir);
}

void virtual_set_dir(page_dir_t *dir)
{
paging_load_pdbr((uint32_t)dir);
paging_enable(true);
}

void virtual_map_page(page_dir_t *dir, uint32_t phys, uint32_t virt, bool present)
{
set_table_entry(dir, phys, virt, present);
}

void virtual_map_kernel(page_dir_t *dir)
{
pd_entry_t *pde;

pde = get_dir_entry(kern_dir, 0x0);
set_dir_entry(dir, 0x0, (page_table_t *)(pde->frame << 12));

pde = get_dir_entry(kern_dir, KERNEL_CODE_VADDRESS);
set_dir_entry(dir, KERNEL_CODE_VADDRESS, (page_table_t *)(pde->frame << 12));
}

pd_entry_t* get_dir_entry(page_dir_t *dir, uint32_t virt)
{
dir = (page_dir_t *)map_quick((uint32_t)dir);
pd_entry_t *e = &dir->entries[PAGE_DIR_INDEX(virt)];
return &dir->entries[PAGE_DIR_INDEX(virt)];
}

void set_dir_entry(page_dir_t *dir, uint32_t virt, page_table_t *pt)
{
pd_entry_t *pde = get_dir_entry(dir, virt);

pde->present = 1;
pde->writable = 1;
pde->user = 0;
pde->writethru = 0;
pde->nocache = 0;
pde->accessed = 0;
pde->size_4mb = 0;
pde->global = 0;
pde->frame = (uint32_t)pt >> 12;
}

pt_entry_t* get_table_entry(page_dir_t *dir, uint32_t virt)
{
pd_entry_t *pde = get_dir_entry(dir, virt);
page_table_t *table = (page_table_t *)(pde->frame << 12);

if (table == NULL)
{
table = (page_table_t *)physical_alloc_block();
set_dir_entry(dir, virt, table);

unsigned int i;
for (i = 0; i < PAGES_PER_TABLE; i++)
set_table_entry(dir, 0x0, virt + (i * PAGE_SIZE), false);
}

table = (page_table_t *)map_quick((uint32_t)table);
return (pt_entry_t *)&table->entries[PAGE_TABLE_INDEX(virt)];
}

void set_table_entry(page_dir_t *dir, uint32_t phys, uint32_t virt, bool present)
{
pt_entry_t *pte = get_table_entry(dir, PAGE_ALIGN(virt));

pte->present = present;
pte->writable = 1;
pte->user = 0;
pte->writethru = 0;
pte->nocache = 0;
pte->dirty = 0;
pte->attr_index = 0;
pte->global = 0;
pte->frame = PAGE_ALIGN(phys) >> 12;
}

uint32_t map_quick(uint32_t addr)
{
GET_PTE(QUICKMAP_ADDR)->frame = PAGE_ALIGN(addr) >> 12;
paging_flush_tlb_entry(QUICKMAP_ADDR);
return QUICKMAP_ADDR;
}

void interrupt page_fault(registers_t *regs)
{
uint32_t virt;
asm volatile ("movl %%cr2, %0" : "=r" (virt));
kprintf("\nError accessing address 0x%x", virt);
kpanic("Page Fault");
}

最佳答案

请参阅此问题重新 __attribute__(packed)
引用:
... __attribute__((packed)) 在某些系统上可能不安全...还有一些系统,其中未对齐的访问悄悄地忽略了地址的低位,导致它访问错误的内存块.

尝试使用 pragma (pack) ( and here ) 而不是:

#pragma pack(1) // exact fit - no padding; placed at top of pragma pack stack
struct pd_entry
{
...
};
struct pt_entry
{
...
};
#pragma pack(pop) //restore previous pragma pack stack

[编辑]
根据您对使用 uint32_t 的评论,如果您想保留访问各个位的能力,您可以使结构成为与 uint31_t union 的一部分:

#pragma pack(1) // exact fit - no padding; placed at top of pragma pack stack
union
{
uint32_t ui32;
struct pd_entry
{
...
};
}
...
#pragma pack(pop) //restore previous pragma pack stack

并使用 orand 以及 uint32_t 来设置,并使用结构的成员检查值。

关于C 指针未设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13090646/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com