#ifndef PLATFORM_H_INCLUDED
#define PLATFORM_H_INCLUDED
#define STACK_SIZE 4096 /*struct thread_t size is 2K*/
#define PAGE_SIZE 4096
/*Segment*/
#define GDT_SEL(gdt) ((gdt) << 3)
#define GDT_NULL 0
#define GDT_KERNEL_CS 1
#define GDT_KERNEL_DS 2
#define GDT_USER_CS 3
#define GDT_USER_DS 4
#define GDT_TSS 5
#define GDT_ENTRYS 6
#define SEL_RPL0 0/*ring 0*/
#define SEL_RPL3 3/*ring 3*/
#define KERNEL_CS_SEL (GDT_SEL(GDT_KERNEL_CS) + SEL_RPL0)
#define KERNEL_DS_SEL (GDT_SEL(GDT_KERNEL_DS) + SEL_RPL0)
#define USER_CS_SEL (GDT_SEL(GDT_USER_CS) + SEL_RPL3)
#define USER_DS_SEL (GDT_SEL(GDT_USER_DS) + SEL_RPL3)
#ifndef __ASSEMBLY__
#include "types.h"
#define SECTION(s) __attribute__((__section__(s)))
#define USED __attribute__((__used__))
#define ALIGN(n) __attribute__((aligned(n)))
#define PACKED __attribute__((packed))
/**kernel.ld define**/
extern uint32_t kernelStart;
extern uint32_t kernelEnd;
/**bootinfo.c define**/
#include
extern struct MultibootInfo bootInfo;
static inline void iodelay()
{
asm volatile("pushl %eax; inb $0x80,%al; inb $0x80,%al; popl %eax");
}
static inline uint8_t inb(uint32_t port)
{
uint8_t value;
asm volatile ("inb %w1, %b0" : "=a"(value) : "Nd"(port));
return value;
}
static inline void outb(uint32_t port, uint8_t value)
{
asm volatile ("outb %b0, %w1" : : "a"(value), "Nd"(port));
}
static inline void outb_p(uint32_t port, uint8_t value)
{
outb(port, value);
iodelay();
}
static inline void outw(uint16_t port, uint16_t v)
{
asm volatile("outw %0,%1" :: "a" (v), "dN" (port));
}
static inline uint16_t inw(uint16_t port)
{
uint16_t v;
asm volatile("inw %1,%0" : "=a" (v) : "dN" (port));
return v;
}
static inline void outl(uint16_t port, uint32_t v)
{
asm volatile("outl %0,%1" : : "a" (v), "dN" (port));
}
static inline uint32_t inl(uint16_t port)
{
uint32_t v;
asm volatile("inl %w1,%0" : "=a" (v) : "dN" (port));
return v;
}
#define insw(port,buf,nr) asm volatile("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"ecx","edi")
#define outsw(port,buf,nr) asm volatile("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"ecx","esi")
static inline void cli()
{
asm volatile("cli": : :"memory");
}
static inline void sti()
{
asm volatile("sti": : :"memory");
}
static inline void halt()
{
asm volatile("hlt": : :"memory");
}
struct pt_regs
{
uint32_t gs;
uint32_t fs;
uint32_t es;
uint32_t ds;
uint32_t edi;
uint32_t esi;
uint32_t ebp;
uint32_t esp;
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
uint32_t eax;
uint32_t int_no;
uint32_t err_code;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
} PACKED;
/**gdt**/
#define GDT_TYPE_CODE0 0x9a
#define GDT_TYPE_CODE3 0xfa
#define GDT_TYPE_DATA0 0x92
#define GDT_TYPE_DATA3 0xf2
#define GDT_TYPE_TSS0 0x89
#define GDT_MODE_32 (1 << 2)
#define GDT_GRAN_4K (1 << 3)
typedef struct gdt_entry
{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_high1;
uint8_t type;
uint8_t limit_high:4;
uint8_t flags:4;
uint8_t base_high2;
} PACKED gdt_entry_t;
typedef struct gdt
{
gdt_entry_t entries[GDT_ENTRYS];
} PACKED gdt_t;
typedef struct gdt_ptr
{
uint16_t limit;
uint32_t base;
} PACKED gdt_ptr_t;
void dump_gdt(gdt_ptr_t *ptr);
/*Reload all the segment registers from the new GDT.*/
static inline void set_ss(uint16_t ss)
{
asm volatile("movw %w0,%%ss" : : "r" (ss));
}
static inline void set_es(uint16_t es)
{
asm volatile("movw %w0,%%es" : : "r" (es));
}
static inline void set_ds(uint16_t ds)
{
asm volatile("movw %w0,%%ds" : : "r" (ds));
}
static inline void load_gdt(const struct gdt_ptr *dtr)
{
asm volatile("lgdt %0"::"m" (*dtr));
asm volatile("ljmp %0,$1f; 1:" : : "i" (KERNEL_CS_SEL));
set_ds(KERNEL_DS_SEL);
set_es(KERNEL_DS_SEL);
set_ss(KERNEL_DS_SEL);
}
/**idt**/
#define IDT_TRAP_GATE 0x8f
#define IDT_INT_GATE 0x8e
#define IDT_SYS_GATE 0xee
typedef struct idt_entry
{
uint16_t offset_low;
uint16_t segment;
uint8_t reserved;
uint8_t flags;
uint16_t offset_high;
} PACKED idt_entry_t;
typedef struct idt_ptr
{
uint16_t limit;
uint32_t base;
} PACKED idt_ptr_t;
static inline void load_idt(const struct idt_ptr *dtr)
{
asm volatile("lidt %0"::"m" (*dtr));
}
/**kernel init order**/
#define INIT_GDT 1
#define INIT_TSS 2
#define INIT_MEM 10
#define INIT_IDT 20
#define INIT_TIMER 30
#define INIT_DEV 40
#define INIT_THREAD 50
#define INIT_NET 90
/** Stringfies the given input. */
#define STR(x) #x
#define ISTR(x) STR(x)
/**Declares a function for initialization.*/
#define INITFUNC(func,level) static uint32_t __initcall_##level SECTION((".init" ISTR(level))) USED = (uint32_t)func;
typedef void InitHandler();
#define EXEC_INIT(from,to) \
{ \
uint32_t *i; \
for (i = (from); i < (to); i++) \
{ \
(*(InitHandler **) i)(); \
} \
}
/*kernel.ld define*/
extern uint32_t initStart;
extern uint32_t initEnd;
/***************************************************************************/
#define IRQBASE 0x20
#define IRQ2INTR(irq) (IRQBASE + (irq))
#define IRQ_TIMER 0
#define IRQ_KEYBOARD 1
#define IRQ_SERAL1 3
#define IRQ_SERPR2 4
#define IRQ_FD 6
#define IRQ_PARA 7
#define IRQ_RTC 8
#define IRQ_AUX 12
#define IRQ_MATHCOPRERR 13
#define IRQ_HD 14
/*
#define INTR_FPU 7
#define INTR_PAGE_FAULT 14
#define INTR_SYSTEM_CALL 0X80
*/
#define MAX_HANDLED_INTR 0x30
typedef int (*pintr_t)(int intr_no, void *arg, struct pt_regs *regs);
void irq_attach(int intr_no, pintr_t func , void *parm, char *msg);
void enable_irq(uint32_t irq);
void disable_irq(uint32_t irq);
/***************************************************************************/
/* 从特权级0移动到特权级3 */
#define move_to_user_mode() \
__asm__ ( \
"movl %%esp, %%eax\n\t" \
/* ss */ "pushl $0x23\n\t" \
/* esp */ "pushl %%eax\n\t" \
/* eflags */ "pushfl\n\t" \
\
/* 复位eflags中的NT位, 如果该位置位, 则硬件会自动切换回上一任务 */ \
"andl $0xffffbfff, (%%esp)\n\t" \
"popfl\n\t"\
"pushfl\n\t"\
\
/* cs */ "pushl $0x1B\n\t" \
/* eip */ "pushl $1f\n\t" \
"iret\n\t" \
"1:\n\t" \
"movl $0x23, %%eax\n\t" \
"movw %%ax, %%ds\n\t" \
"movw %%ax, %%es\n\t" \
"movw %%ax, %%fs\n\t" \
"movw %%ax, %%gs\n\t" \
:::"%eax" \
)
static inline void store_gdt(gdt_ptr_t *dtr)
{
asm volatile("sgdt %0":"=m" (*dtr));
}
typedef struct tss_struct
{
uint16_t back_link,__blh;
uint32_t esp0;
uint16_t ss0,__ss0h;
uint32_t esp1;
uint16_t ss1,__ss1h;
uint32_t esp2;
uint16_t ss2,__ss2h;
uint32_t cr3;
uint32_t eip;
uint32_t eflags;
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;
uint16_t es, __esh;
uint16_t cs, __csh;
uint16_t ss, __ssh;
uint16_t ds, __dsh;
uint16_t fs, __fsh;
uint16_t gs, __gsh;
uint16_t ldt, ldt_high;
uint16_t reserved;
uint16_t io_map_base;
} PACKED tss_t;
tss_t *tss_get();
static inline void load_tr()
{
asm volatile("ltr %%ax"::"a" (GDT_SEL(GDT_TSS)));
}
static uint32_t __force_order;
static inline uint32_t get_cs()
{
uint32_t val;
asm volatile("mov %%cs,%0\n\t" : "=r" (val), "=m" (__force_order));
return val;
}
static inline uint32_t get_ds()
{
uint32_t val;
asm volatile("mov %%ds,%0\n\t" : "=r" (val), "=m" (__force_order));
return val;
}
static inline uint32_t get_es()
{
uint32_t val;
asm volatile("mov %%es,%0\n\t" : "=r" (val), "=m" (__force_order));
return val;
}
static inline uint32_t get_fs()
{
uint32_t val;
asm volatile("mov %%fs,%0\n\t" : "=r" (val), "=m" (__force_order));
return val;
}
static inline uint32_t get_gs()
{
uint32_t val;
asm volatile("mov %%gs,%0\n\t" : "=r" (val), "=m" (__force_order));
return val;
}
static inline uint32_t get_ss()
{
uint32_t val;
asm volatile("mov %%ss,%0\n\t" : "=r" (val), "=m" (__force_order));
return val;
}
static inline uint32_t get_sp()
{
uint32_t val;
asm volatile("mov %%esp,%0\n\t" : "=r" (val), "=m" (__force_order));
return val;
}
#endif
#endif