提交 bcdd142c 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Start of trap 64-bitification.

上级 6f4a90b3
...@@ -12,7 +12,8 @@ OBJS = \ ...@@ -12,7 +12,8 @@ OBJS = \
string.o \ string.o \
uart.o \ uart.o \
vm.o \ vm.o \
trap.o trap.o \
trapasm.o
# Cross-compiling (e.g., on Mac OS X) # Cross-compiling (e.g., on Mac OS X)
TOOLPREFIX ?= x86_64-jos-elf- TOOLPREFIX ?= x86_64-jos-elf-
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// See Chapter 8 & Appendix C of Intel processor manual volume 3. // See Chapter 8 & Appendix C of Intel processor manual volume 3.
#include "types.h" #include "types.h"
#include "x86.h"
#include "param.h" #include "param.h"
#include "x86.h"
#include "kernel.h" #include "kernel.h"
#include "traps.h" #include "traps.h"
#include "bits.h" #include "bits.h"
......
...@@ -5,25 +5,24 @@ ...@@ -5,25 +5,24 @@
extern void inituart(void); extern void inituart(void);
extern void initcga(void); extern void initcga(void);
extern void initconsole(void); extern void initconsole(void);
extern void initpg(void);
extern void initmp(void); extern void initmp(void);
extern void initlapic(void); extern void initlapic(void);
extern void inittrap(void);
extern void initpg(void);
extern void initseg(void); extern void initseg(void);
extern void inittrap(void);
void void
cmain(void) cmain(void)
{ {
inituart(); inituart();
initcga(); initcga();
initconsole(); initconsole();
inittrap();
initpg(); initpg();
initmp(); initmp();
initlapic(); initlapic();
initseg(); initseg();
#if 0
inittrap();
#endif
cprintf("ncpu %d\n", ncpu); cprintf("ncpu %d\n", ncpu);
panic("end"); panic("end");
......
...@@ -39,21 +39,30 @@ ...@@ -39,21 +39,30 @@
#define PTE_ADDR(pte) ((uptr)(pte) & ~0xFFF) #define PTE_ADDR(pte) ((uptr)(pte) & ~0xFFF)
struct segdesc { struct segdesc {
int lim_15_0 : 16; // Low bits of segment limit u16 limit0;
int base_15_0 : 16; // Low bits of segment base address u16 base0;
int base_23_16 : 8; // Middle bits of segment base address u8 base1;
int type : 4; // Segment type (see STS_ constants) u8 bits;
int s : 1; // 0 = system, 1 = application u8 bitslimit1;
int dpl : 2; // Descriptor Privilege Level u8 base2;
int p : 1; // Present
int lim_19_16 : 4; // High bits of segment limit
int avl : 1; // Unused (available for software use)
int rsv1 : 1; // Reserved
int db : 1; // 0 = 16-bit segment, 1 = 32-bit segment
int g : 1; // Granularity: limit scaled by 4K when set
int base_31_24 : 8; // High bits of segment base address
}; };
// SEGDESC constructs a segment descriptor literal
// with the given, base, limit, and type bits.
#define SEGDESC(base, limit, bits) (struct segdesc){ \
(limit)&0xffff, (base)&0xffff, \
((base)>>16)&0xff, \
(bits)&0xff, \
(((bits)>>4)&0xf0) | ((limit>>16)&0xf), \
((base)>>24)&0xff, \
}
// SEGDESCHI constructs an extension segment descriptor
// literal that records the high bits of base.
#define SEGDESCHI(base) (struct segdesc){ \
((base)>>32)&0xffff, ((base)>>48)&0xffff, \
}
// Segment selectors (indexes) in our GDTs. // Segment selectors (indexes) in our GDTs.
// Defined by our convention, not the architecture. // Defined by our convention, not the architecture.
#define KCSEG32 (1<<3) /* kernel 32-bit code segment */ #define KCSEG32 (1<<3) /* kernel 32-bit code segment */
...@@ -63,3 +72,56 @@ struct segdesc { ...@@ -63,3 +72,56 @@ struct segdesc {
#define UCSEG (6<<3) /* user code segment */ #define UCSEG (6<<3) /* user code segment */
#define UDSEG (7<<3) /* user data segment */ #define UDSEG (7<<3) /* user data segment */
#define NSEGS 8 #define NSEGS 8
// User segment bits (SEG_S set).
#define SEG_A (1<<0) /* segment accessed bit */
#define SEG_R (1<<1) /* readable (code) */
#define SEG_W (1<<1) /* writable (data) */
#define SEG_C (1<<2) /* conforming segment (code) */
#define SEG_E (1<<2) /* expand-down bit (data) */
#define SEG_CODE (1<<3) /* code segment (instead of data) */
// System segment bits (SEG_S is clear).
#define SEG_LDT (2<<0) /* local descriptor table */
#define SEG_TSS64A (9<<0) /* available 64-bit TSS */
#define SEG_TSS64B (11<<0) /* busy 64-bit TSS */
#define SEG_CALL64 (12<<0) /* 64-bit call gate */
#define SEG_INTR64 (14<<0) /* 64-bit interrupt gate */
#define SEG_TRAP64 (15<<0) /* 64-bit trap gate */
// User and system segment bits.
#define SEG_S (1<<4) /* if 0, system descriptor */
#define SEG_DPL(x) ((x)<<5) /* descriptor privilege level (2 bits) */
#define SEG_P (1<<7) /* segment present */
#define SEG_AVL (1<<8) /* available for operating system use */
#define SEG_L (1<<9) /* long mode */
#define SEG_D (1<<10) /* default operation size 32-bit */
#define SEG_G (1<<11) /* granularity */
struct intdesc
{
u16 rip0;
u16 cs;
u8 reserved0;
u8 bits;
u16 rip1;
u32 rip2;
u32 reserved1;
};
// See section 4.6 of amd64 vol2
struct desctr
{
u16 limit;
u64 base;
} __attribute__((packed, aligned(16)));
#define INT_P (1<<7) /* interrupt descriptor present */
// INTDESC constructs an interrupt descriptor literal
// that records the given code segment, instruction pointer,
// and type bits.
#define INTDESC(cs, rip, bits) (struct intdesc){ \
(rip)&0xffff, (cs), 0, bits, ((rip)>>16)&0xffff, \
(uint64)(rip)>>32, 0, \
}
#include "vmx.h" #include "types.h"
#include "amd64.h" #include "mmu.h"
#include "kernel.h"
extern Segdesc bootgdt[NUMSEG]; #include "x86.h"
void struct segdesc __attribute__((aligned(16))) bootgdt[NSEGS] = {
inittrap(void) // null
{ SEGDESC(0, 0, 0),
// 32-bit kernel code
} SEGDESC(0, 0xfffff, SEG_R|SEG_CODE|SEG_S|SEG_DPL(0)|SEG_P|SEG_D|SEG_G),
// 64-bit kernel code
// Bootstrap GDT. Used by boot.S but defined in C SEGDESC(0, 0, SEG_R|SEG_CODE|SEG_S|SEG_DPL(0)|SEG_P|SEG_L|SEG_G),
// so we can use the data structure macros in amd64.h. // kernel data
Segdesc bootgdt[NUMSEG] = { SEGDESC(0, 0xfffff, SEG_W|SEG_S|SEG_DPL(0)|SEG_P|SEG_D|SEG_G)
SEGDESC(0, 0, 0), // null
SEGDESC(0, 0xfffff, SEG_R|SEG_CODE|SEG_S|SEG_DPL(0)|SEG_P|SEG_D|SEG_G), // 32-bit kernel code
SEGDESC(0, 0, SEG_R|SEG_CODE|SEG_S|SEG_DPL(0)|SEG_P|SEG_L|SEG_G), // 64-bit kernel code
SEGDESC(0, 0xfffff, SEG_W|SEG_S|SEG_DPL(0)|SEG_P|SEG_D|SEG_G), // kernel data
}; };
struct intdesc idt[256] __attribute__((aligned(16)));
#if 0 // boot.S
extern u64 trapentry[];
Intdesc idt[256];
Segdesc gdt[NUMSEG];
extern Segdesc bootgdt[NUMSEG];
extern uint64 trapentry[];
static Taskseg ts;
static char istack[8192];
void void
inittrap(void) trap(void)
{ {
int i; panic("trap");
uint32 bits;
uint64 base, entry;
bits = INT_P | SEG_INTR64; // present, interrupt gate
for(i=0; i<256; i++) {
entry = trapentry[i];
idt[i] = INTDESC(KCSEG, entry, bits);
}
memmove(gdt, bootgdt, sizeof gdt);
base = (uintptr)&ts;
gdt[TSSSEG>>3] = SEGDESC(base, (sizeof ts-1), SEG_P|SEG_TSS64A);
gdt[(TSSSEG>>3)+1] = SEGDESCHI(base);
ts.rsp0 = (uintptr)istack+sizeof istack;
lidt(idt, sizeof idt);
lgdt(gdt, sizeof gdt);
ltr(TSSSEG);
} }
void void
trap(void) inittrap(void)
{ {
panic("trap"); volatile struct desctr dtr;
uint64 entry;
uint32 bits;
int i;
bits = INT_P | SEG_INTR64; // present, interrupt gate
for(i=0; i<256; i++) {
entry = trapentry[i];
idt[i] = INTDESC(KCSEG, entry, bits);
}
dtr.limit = sizeof(idt) - 1;
dtr.base = (u64)idt;
lidt((void *)&dtr.limit);
// Reload GDT from kernel VA
dtr.limit = sizeof(bootgdt) - 1;
dtr.base = (u64)bootgdt;
lgdt((void *)&dtr.limit);
} }
#endif
#define SEG_KCODE 1 // kernel code #define _TRAP(x, l) \
#define SEG_KDATA 2 // kernel data+stack .globl trap ## x; \
#define SEG_KCPU 3 // kernel per-cpu data .align 8; \
trap ## x: \
pushq $x; \
jmp l; \
.data; \
.quad trap ## x; \
.previous
# vectors.S sends all traps here. #define TRAP(x) _TRAP(x, trappush)
.globl alltraps #define TRAPCODE(x) _TRAP(x, trapcommon)
alltraps:
# Build trap frame.
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushal
# Set up data and per-cpu segments.
movw $(SEG_KDATA<<3), %ax
movw %ax, %ds
movw %ax, %es
movw $(SEG_KCPU<<3), %ax
movw %ax, %fs
movw %ax, %gs
# Call trap(tf), where tf=%esp .code64
pushl %esp .globl trappush
call trap .align 8
addl $4, %esp trappush:
pushq $0 // error code
trapcommon:
// TODO(rsc): Do we need to push ds, es, fs, gs?
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %r11
pushq %r10
pushq %r9
pushq %r8
pushq %rdi
pushq %rsi
pushq %rbp
pushq $0 // sp
pushq %rbx
pushq %rdx
pushq %rcx
pushq %rax
movq %rsp, %rdi // first argument to trap
call trap
# Return falls through to trapret... .data
.globl trapret .align 8
trapret: .globl trapentry
popal trapentry:
popl %gs
popl %fs .text
popl %es // See section 6.15 of Vol 3.
popl %ds TRAP(0) // divide error
addl $0x8, %esp # trapno and errcode TRAP(1) // debug exception
iret TRAP(2) // NMI
TRAP(3) // breakpoint
TRAP(4) // overflow
TRAP(5) // bound
TRAP(6) // invalid opcode
TRAP(7) // device not available
TRAPCODE(8) // double fault - has error code
TRAP(9) // coprocessor overrun
TRAPCODE(10) // invalid TSS
TRAPCODE(11) // segment not present
TRAPCODE(12) // stack fault
TRAPCODE(13) // general protection fault
TRAPCODE(14) // page fault
TRAP(15) // not defined
TRAP(16) // fpu error
TRAPCODE(17) // alignment check
TRAP(18) // machine check
TRAP(19) // simd
# Edit .+1,|seq 20 255 | sed 's/.*/ TRAP(&)/'
TRAP(20)
TRAP(21)
TRAP(22)
TRAP(23)
TRAP(24)
TRAP(25)
TRAP(26)
TRAP(27)
TRAP(28)
TRAP(29)
TRAP(30)
TRAP(31)
TRAP(32)
TRAP(33)
TRAP(34)
TRAP(35)
TRAP(36)
TRAP(37)
TRAP(38)
TRAP(39)
TRAP(40)
TRAP(41)
TRAP(42)
TRAP(43)
TRAP(44)
TRAP(45)
TRAP(46)
TRAP(47)
TRAP(48)
TRAP(49)
TRAP(50)
TRAP(51)
TRAP(52)
TRAP(53)
TRAP(54)
TRAP(55)
TRAP(56)
TRAP(57)
TRAP(58)
TRAP(59)
TRAP(60)
TRAP(61)
TRAP(62)
TRAP(63)
TRAP(64)
TRAP(65)
TRAP(66)
TRAP(67)
TRAP(68)
TRAP(69)
TRAP(70)
TRAP(71)
TRAP(72)
TRAP(73)
TRAP(74)
TRAP(75)
TRAP(76)
TRAP(77)
TRAP(78)
TRAP(79)
TRAP(80)
TRAP(81)
TRAP(82)
TRAP(83)
TRAP(84)
TRAP(85)
TRAP(86)
TRAP(87)
TRAP(88)
TRAP(89)
TRAP(90)
TRAP(91)
TRAP(92)
TRAP(93)
TRAP(94)
TRAP(95)
TRAP(96)
TRAP(97)
TRAP(98)
TRAP(99)
TRAP(100)
TRAP(101)
TRAP(102)
TRAP(103)
TRAP(104)
TRAP(105)
TRAP(106)
TRAP(107)
TRAP(108)
TRAP(109)
TRAP(110)
TRAP(111)
TRAP(112)
TRAP(113)
TRAP(114)
TRAP(115)
TRAP(116)
TRAP(117)
TRAP(118)
TRAP(119)
TRAP(120)
TRAP(121)
TRAP(122)
TRAP(123)
TRAP(124)
TRAP(125)
TRAP(126)
TRAP(127)
TRAP(128)
TRAP(129)
TRAP(130)
TRAP(131)
TRAP(132)
TRAP(133)
TRAP(134)
TRAP(135)
TRAP(136)
TRAP(137)
TRAP(138)
TRAP(139)
TRAP(140)
TRAP(141)
TRAP(142)
TRAP(143)
TRAP(144)
TRAP(145)
TRAP(146)
TRAP(147)
TRAP(148)
TRAP(149)
TRAP(150)
TRAP(151)
TRAP(152)
TRAP(153)
TRAP(154)
TRAP(155)
TRAP(156)
TRAP(157)
TRAP(158)
TRAP(159)
TRAP(160)
TRAP(161)
TRAP(162)
TRAP(163)
TRAP(164)
TRAP(165)
TRAP(166)
TRAP(167)
TRAP(168)
TRAP(169)
TRAP(170)
TRAP(171)
TRAP(172)
TRAP(173)
TRAP(174)
TRAP(175)
TRAP(176)
TRAP(177)
TRAP(178)
TRAP(179)
TRAP(180)
TRAP(181)
TRAP(182)
TRAP(183)
TRAP(184)
TRAP(185)
TRAP(186)
TRAP(187)
TRAP(188)
TRAP(189)
TRAP(190)
TRAP(191)
TRAP(192)
TRAP(193)
TRAP(194)
TRAP(195)
TRAP(196)
TRAP(197)
TRAP(198)
TRAP(199)
TRAP(200)
TRAP(201)
TRAP(202)
TRAP(203)
TRAP(204)
TRAP(205)
TRAP(206)
TRAP(207)
TRAP(208)
TRAP(209)
TRAP(210)
TRAP(211)
TRAP(212)
TRAP(213)
TRAP(214)
TRAP(215)
TRAP(216)
TRAP(217)
TRAP(218)
TRAP(219)
TRAP(220)
TRAP(221)
TRAP(222)
TRAP(223)
TRAP(224)
TRAP(225)
TRAP(226)
TRAP(227)
TRAP(228)
TRAP(229)
TRAP(230)
TRAP(231)
TRAP(232)
TRAP(233)
TRAP(234)
TRAP(235)
TRAP(236)
TRAP(237)
TRAP(238)
TRAP(239)
TRAP(240)
TRAP(241)
TRAP(242)
TRAP(243)
TRAP(244)
TRAP(245)
TRAP(246)
TRAP(247)
TRAP(248)
TRAP(249)
TRAP(250)
TRAP(251)
TRAP(252)
TRAP(253)
TRAP(254)
TRAP(255)
...@@ -67,9 +67,9 @@ pgmap(void *va, void *last, paddr pa) ...@@ -67,9 +67,9 @@ pgmap(void *va, void *last, paddr pa)
void void
initpg(char* (*alloc)(void)) initpg(char* (*alloc)(void))
{ {
pgmap((void *) 0, (void *) PHYSTOP, 0); // Map first 4GB to PBASE
pgmap((void *) PBASE, (void *) (PBASE+(1UL<<32)), 0); pgmap((void *) PBASE, (void *) (PBASE+(1UL<<32)), 0);
// boot.S gets us running with kpml4 // boot.S maps first 1GB to KBASE and gets us running with kpml4
} }
// Set up CPU's kernel segment descriptors. // Set up CPU's kernel segment descriptors.
......
...@@ -71,6 +71,18 @@ nop_pause(void) ...@@ -71,6 +71,18 @@ nop_pause(void)
} }
static inline void static inline void
lidt(void *p)
{
__asm volatile("lidt (%0)" : : "r" (p) : "memory");
}
static inline void
lgdt(void *p)
{
__asm volatile("lgdt (%0)" : : "r" (p) : "memory");
}
static inline void
writegs(u16 v) writegs(u16 v)
{ {
__asm volatile("movw %0, %%gs" : : "r" (v)); __asm volatile("movw %0, %%gs" : : "r" (v));
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论