mirror of
https://git.nju.edu.cn/oslab2023/oslab.git
synced 2024-06-13 04:44:31 +08:00
153 lines
5.2 KiB
C
153 lines
5.2 KiB
C
#ifndef __X86_MEMORY_H__
|
|
#define __X86_MEMORY_H__
|
|
|
|
// CPU rings
|
|
#define DPL_KERN 0x0 // Kernel (ring 0)
|
|
#define DPL_USER 0x3 // User (ring 3)
|
|
|
|
// Application Segment type bits
|
|
#define STA_X 0x8 // Executable segment
|
|
#define STA_W 0x2 // Writeable (non-executable segments)
|
|
#define STA_R 0x2 // Readable (executable segments)
|
|
|
|
// System Segment type bits
|
|
#define STS_T32A 0x9 // Available 32-bit TSS
|
|
#define STS_IG 0xe // 32/64-bit Interrupt Gate
|
|
#define STS_TG 0xf // 32/64-bit Trap Gate
|
|
|
|
// Control Register flags
|
|
#define CR0_PE 0x00000001 // Protection Enable
|
|
#define CR0_PG 0x80000000 // Paging
|
|
|
|
// Page table/directory entry flags
|
|
#define PTE_P 0x001 // Present
|
|
#define PTE_W 0x002 // Writeable
|
|
#define PTE_U 0x004 // User
|
|
|
|
// GDT selectors
|
|
#define KSEL(seg) (((seg) << 3) | DPL_KERN)
|
|
#define USEL(seg) (((seg) << 3) | DPL_USER)
|
|
|
|
#define NR_SEG 6 // GDT size
|
|
#define SEG_KCODE 1 // Kernel code
|
|
#define SEG_KDATA 2 // Kernel data/stack
|
|
#define SEG_UCODE 3 // User code
|
|
#define SEG_UDATA 4 // User data/stack
|
|
#define SEG_TSS 5 // Global unique task state segement
|
|
|
|
#ifndef __ASSEMBLER__
|
|
|
|
#include <stdint.h>
|
|
|
|
// Segment Descriptor
|
|
typedef struct {
|
|
uint32_t lim_15_0 : 16; // Low bits of segment limit
|
|
uint32_t base_15_0 : 16; // Low bits of segment base address
|
|
uint32_t base_23_16 : 8; // Middle bits of segment base address
|
|
uint32_t type : 4; // Segment type (see STS_ constants)
|
|
uint32_t s : 1; // 0 = system, 1 = application
|
|
uint32_t dpl : 2; // Descriptor Privilege Level
|
|
uint32_t p : 1; // Present
|
|
uint32_t lim_19_16 : 4; // High bits of segment limit
|
|
uint32_t avl : 1; // Unused (available for software use)
|
|
uint32_t l : 1; // 64-bit segment
|
|
uint32_t db : 1; // 32-bit segment
|
|
uint32_t g : 1; // Granularity: limit scaled by 4K when set
|
|
uint32_t base_31_24 : 8; // High bits of segment base address
|
|
} SegDesc;
|
|
|
|
// Task State Segment (TSS)
|
|
typedef struct {
|
|
uint32_t link; // Unused
|
|
uint32_t esp0; // Stack pointers and segment selectors
|
|
uint32_t ss0; // after an increase in privilege level
|
|
uint32_t padding[23];
|
|
} __attribute__((packed)) TSS32;
|
|
|
|
#define SEG16(type, base, lim, dpl) (SegDesc) \
|
|
{ (lim) & 0xffff, (uintptr_t)(base) & 0xffff, \
|
|
((uintptr_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \
|
|
(uintptr_t)(lim) >> 16, 0, 0, 1, 0, (uintptr_t)(base) >> 24 }
|
|
|
|
#define SEG32(type, base, lim, dpl) (SegDesc) \
|
|
{ ((lim) >> 12) & 0xffff, (uintptr_t)(base) & 0xffff, \
|
|
((uintptr_t)(base) >> 16) & 0xff, type, 1, dpl, 1, \
|
|
(uintptr_t)(lim) >> 28, 0, 0, 1, 1, (uintptr_t)(base) >> 24 }
|
|
|
|
|
|
#define KER_MEM 0x00200000 // the max static memory of kernel
|
|
#define PHY_MEM 0x08000000 // QEMU has 128MB physical memory
|
|
#define USR_MEM 0xc0000000 // the memory top of user proc
|
|
|
|
#define PGSIZE 4096 // page size in x86
|
|
#define PGMASK (PGSIZE - 1) // page mask in x86
|
|
#define PGBITS 12 // page bits in x86
|
|
#define NR_PDE 1024 // number of PDE in PD
|
|
#define NR_PTE 1024 // number of PTE in PT
|
|
#define PT_SIZE ((NR_PTE) * (PGSIZE)) // size of address a PT can cover
|
|
#define PG_ALIGN __attribute((aligned(PGSIZE))) // force data aligned with page
|
|
|
|
#define PAGE_DOWN(addr) (((uint32_t)(addr)) & (~PGMASK))
|
|
#define PAGE_UP(addr) (((uint32_t)(addr) + PGMASK) & (~PGMASK))
|
|
|
|
#define DIR_MASK 0xffc00000
|
|
#define DIR_SHIFT 22
|
|
#define TBL_MASK 0x003ff000
|
|
#define TBL_SHIFT 12
|
|
#define OFF_MASK 0x00000fff
|
|
|
|
// calculate the PD-index/PT-index/offset of a address
|
|
#define ADDR2DIR(addr) (((uint32_t)(addr) & DIR_MASK) >> DIR_SHIFT)
|
|
#define ADDR2TBL(addr) ((((uint32_t)(addr)) & TBL_MASK) >> TBL_SHIFT)
|
|
#define ADDR2OFF(addr) (((uint32_t)(addr)) & OFF_MASK)
|
|
|
|
/* the 32bit Page Directory(first level page table) data structure */
|
|
typedef union PageDirectoryEntry {
|
|
struct {
|
|
uint32_t present : 1;
|
|
uint32_t read_write : 1;
|
|
uint32_t user_supervisor : 1;
|
|
uint32_t page_write_through : 1;
|
|
uint32_t page_cache_disable : 1;
|
|
uint32_t accessed : 1;
|
|
uint32_t pad0 : 6;
|
|
uint32_t page_frame : 20;
|
|
};
|
|
uint32_t val;
|
|
} PDE;
|
|
|
|
typedef struct PageDirectory {
|
|
PDE pde[NR_PDE] PG_ALIGN;
|
|
} PD;
|
|
|
|
/* the 32bit Page Table Entry(second level page table) data structure */
|
|
typedef union PageTableEntry {
|
|
struct {
|
|
uint32_t present : 1;
|
|
uint32_t read_write : 1;
|
|
uint32_t user_supervisor : 1;
|
|
uint32_t page_write_through : 1;
|
|
uint32_t page_cache_disable : 1;
|
|
uint32_t accessed : 1;
|
|
uint32_t dirty : 1;
|
|
uint32_t pad0 : 1;
|
|
uint32_t global : 1;
|
|
uint32_t pad1 : 3;
|
|
uint32_t page_frame : 20;
|
|
};
|
|
uint32_t val;
|
|
} PTE;
|
|
|
|
typedef struct PageTable {
|
|
PTE pte[NR_PTE] PG_ALIGN;
|
|
} PT;
|
|
|
|
#define MAKE_PDE(addr, prot) (PAGE_DOWN(addr) | (prot) | (PTE_P))
|
|
#define MAKE_PTE(addr, prot) (PAGE_DOWN(addr) | (prot) | (PTE_P))
|
|
|
|
#define PDE2PT(pde) ((PT*)((pde).page_frame << PGBITS))
|
|
#define PTE2PG(pte) ((void*)((pte).page_frame << PGBITS))
|
|
|
|
#endif // __ASSEMBLER__
|
|
#endif // __X86_MEMORY_H__
|