} __attribute__((packed)) madt_t;
-void parse_madt(void *addr) {
+void parse_madt(paddr_t addr) {
if(0 == addr) {
printk("MADT addr is null\n");
return;
}
}
-void parse_rsdt(void *addr) {
+void parse_rsdt(paddr_t addr) {
if(0 == addr) {
printk("RSDT addr is null\n");
return;
for(int i=0; i<table_count; i++) {
uint32_t table_phys_addr = rsdt->table_ptrs[i];
- page_map((void *)table_phys_addr, (void *)table_phys_addr, PAGE_P | PAGE_WR);
+ page_map((vaddr_t)table_phys_addr, (paddr_t)table_phys_addr, PAGE_P | PAGE_WR);
acpi_sdt_header_t *table = (acpi_sdt_header_t *)table_phys_addr;
if(table == 0) {
}
printk("ACPI table %u signature %s addr %08x len %u\n", i, sig, table_phys_addr, table->length);
if(memcmp(sig, "APIC", 4) == 0) {
- parse_madt(table);
+ parse_madt((paddr_t)table);
}
}
};
-void page_map(void *vaddr, void *paddr, uint32_t flags);
+void page_map(vaddr_t vaddr, paddr_t paddr, uint32_t flags);
#endif // ASM
typedef unsigned long long uint64_t;
typedef long long int64_t;
+
+typedef uint32_t uintptr_t;
+typedef uint32_t paddr_t;
+typedef uint32_t vaddr_t;
+
typedef int64_t loff_t;
typedef uint32_t dev_t;
printk("apic version: %08lx\n", apic_version);
- unsigned long apic_phys_base_addr = apic_base & 0xFFFFF000;
- unsigned long apic_virt_base_addr = apic_phys_base_addr;
+ paddr_t apic_phys_base_addr = apic_base & 0xFFFFF000;
+ vaddr_t apic_virt_base_addr = apic_phys_base_addr;
#if 0
unsigned long ddd = 0xFEC00000;
while(ddd < 0xFF000000) {
ddd += 0x1000;
}
#endif
- page_map((void*)apic_virt_base_addr, (void*)apic_phys_base_addr, PAGE_P);
+ page_map((vaddr_t)apic_virt_base_addr, (paddr_t)apic_phys_base_addr, PAGE_P);
{
volatile uint32_t *base = (volatile uint32_t *)apic_virt_base_addr;
* ------------------------------------------------------------------------
*/
-.global ring3_entrys
+#define ASM
+#include <syscall.h>
+
# a allocatable 可分配,表示这个节在程序运行时需要加载到内存中
# x executable 可执行,表示这个节包含可执行的代码
# w writable 可写,通常用于数据节
#
# @progbits 包含了程序数据 目标文件中实际包含数据/代码,如.text、.data节
# @nobits 不包含程序数据 目标文件中不占空间,运行时分配零初始化内存,如.bss节
-.section .ring3.entry, "aw", @progbits
-#.type ring3_entry, @function
+.section .ring3.entry, "ax", @progbits
.align 0x1000
-ring3_entrys:
- nop;
- nop;
+ring3_entry:
+ nop
nop
+ nop
+
pushal
- movl $5, %eax
- call get_eip
- get_eip:
- popl %edi
- addl $8,%edi
- movl %esp, %ebp;
- sysenter;
+
+ movl $7, %ebx
+ movl $SYSC_WAIT, %eax
+ call get_eip
+get_eip:
+ # 这里popl取得的就是上一个call指令自动压入栈中的地址
+ # 这个地址就是当前指令的地址
+ popl %edi
+ addl $8,%edi
+ movl %esp, %ebp;
+
+ sysenter
+
popal
+
nop
nop
- jmp ring3_entrys
+ jmp ring3_entry
// 在系统调用前,用户态的esp保存在ebp中
// sysexit指令从ecx中恢复用户态esp
- xchgl %ebp, %ecx
+ movl %ebp, %ecx
sysexit
#include <syscall.h>
#include <system.h>
#include <types.h>
+#include <page.h>
void flush_tlb() {
asm volatile("movl %%cr3, %%eax;"
// ring3只占用一个page,页的起始位置放的是代码,页的末尾当栈用
// ring3的地址直接是物理地址
- extern unsigned long ring3_page_addr;
- extern unsigned long ring3_page_end;
- unsigned long ring3_text_page =(unsigned long) &ring3_page_addr; // 不在内核空间的物理地址
- unsigned long ring3_stack_top = (unsigned long) &ring3_page_end; // 不在内核空间的物理地址
-
- unsigned long ring3_page_vaddr = 0x08000000; // 指定的ring3的虚拟地址
- unsigned long ring3_stack_top_vaddr = ring3_page_vaddr + (ring3_stack_top - ring3_text_page);
- int npte = get_npte(ring3_page_vaddr);
- int npde = get_npde(ring3_page_vaddr);
+ extern char ring3_page_begin;
- // 分配一个页表在用户空间对这页进行映射
- pte_t *pgt = (pte_t *)page2va(alloc_one_page(0));
+ paddr_t ring3_page_addr = (paddr_t)&ring3_page_begin; // 不在内核空间的物理地址
+ paddr_t ring3_stack_top = ring3_page_addr + PAGE_SIZE;
- memset(pgt, 0, PAGE_SIZE);
- pgt[npte] = (pte_t)(ring3_text_page | PAGE_P | PAGE_US | PAGE_WR);
+ vaddr_t ring3_page_vaddr = 0x08000000; // 指定的ring3的虚拟地址
+ vaddr_t ring3_stack_top_vaddr = PAGE_OFFSET - 0x100000;
- // 把这个页表映射到页目录
- pde_t *pgd = pa2va(get_pgd());
- pgd[npde] = (pde_t)(((unsigned long)va2pa(pgt)) | PAGE_P | PAGE_US | PAGE_WR);
+ page_map(ring3_page_vaddr, ring3_page_addr, PAGE_P | PAGE_US);
- // 到此完成了 ring3_page_vaddr -> ring3_text_page的映射
- // 刷新tlb
- flush_tlb();
+ // 这里减去PAGE_SIZE是因为栈是向下生长的,所以得把栈顶虚拟地址空间的前一页映射到ring3_page
+ page_map((ring3_stack_top_vaddr-PAGE_SIZE), ring3_page_addr, PAGE_P | PAGE_US | PAGE_WR);
- // 现在准备返回用户态
- asm volatile("sysexit;" ::"d"(ring3_page_vaddr), "c"(ring3_stack_top_vaddr - 0x10));
+ asm volatile("sysexit;" ::"d"(ring3_page_vaddr), "c"(ring3_stack_top_vaddr));
}
}
-void page_map(void *vaddr, void *paddr, uint32_t flags) {
+void page_map(vaddr_t vaddr, paddr_t paddr, uint32_t flags) {
+ assert(PAGE_ALIGN(vaddr) == vaddr);
+ assert(PAGE_ALIGN(paddr) == paddr);
+ assert(PAGE_FLAGS(flags) == flags);
+
int npde = get_npde(vaddr);
int npte = get_npte(vaddr);
// 获取页目录地址
- uint32_t pgd_pyhs_addr;
- asm("mov %%cr3, %0" : "=r"(pgd_pyhs_addr));
- pde_t *pgd = (pde_t *) pa2va(pgd_pyhs_addr);
+ pde_t *pgd = (pde_t *) pa2va(get_pgd());
pte_t *pgt = 0;
pde_t pde = pgd[npde];
asm volatile("invlpg (%0)" : : "r"(vaddr));
-
- uint32_t cr3 = 0;
- asm("mov %%cr3, %0" : "=r"(cr3));
-
- asm("nop;nop;nop;");
-
- asm("mov %0, %%cr3" : : "r"(cr3));
- // asm volatile("mov %0, %%cr3" : : "r"(pgd_pyhs_addr));
}
eunpaged_rodata = .;
. = ALIGN(0x1000);
- ring3_page_addr = .;
+ ring3_page_begin = .;
.ring3 :
{
*(.ring3.entry)