Map kernel high
Very important to give qemu memory through PHYSTOP :(
This commit is contained in:
		
							parent
							
								
									dccb915282
								
							
						
					
					
						commit
						9aa0337dc1
					
				
					 20 changed files with 208 additions and 71 deletions
				
			
		
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -109,7 +109,7 @@ initcode: initcode.S | ||||||
| 	$(OBJDUMP) -S initcode.o > initcode.asm | 	$(OBJDUMP) -S initcode.o > initcode.asm | ||||||
| 
 | 
 | ||||||
| kernel: $(OBJS) multiboot.o data.o bootother initcode | kernel: $(OBJS) multiboot.o data.o bootother initcode | ||||||
| 	$(LD) $(LDFLAGS) -Ttext 0x100000 -e main -o kernel multiboot.o data.o $(OBJS) -b binary initcode bootother | 	$(LD) $(LDFLAGS) -T kernel.ld -e multiboot_entry -o kernel multiboot.o data.o $(OBJS) -b binary initcode bootother | ||||||
| 	$(OBJDUMP) -S kernel > kernel.asm | 	$(OBJDUMP) -S kernel > kernel.asm | ||||||
| 	$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym | 	$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym | ||||||
| 
 | 
 | ||||||
|  | @ -200,7 +200,7 @@ QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \ | ||||||
| ifndef CPUS | ifndef CPUS | ||||||
| CPUS := 2 | CPUS := 2 | ||||||
| endif | endif | ||||||
| QEMUOPTS = -hdb fs.img xv6.img -smp $(CPUS) | QEMUOPTS = -hdb fs.img xv6.img -smp $(CPUS) -m 512 | ||||||
| 
 | 
 | ||||||
| qemu: fs.img xv6.img | qemu: fs.img xv6.img | ||||||
| 	$(QEMU) -serial mon:stdio $(QEMUOPTS) | 	$(QEMU) -serial mon:stdio $(QEMUOPTS) | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								bootmain.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								bootmain.c
									
										
									
									
									
								
							|  | @ -8,6 +8,7 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "elf.h" | #include "elf.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
|  | #include "memlayout.h" | ||||||
| 
 | 
 | ||||||
| #define SECTSIZE  512 | #define SECTSIZE  512 | ||||||
| 
 | 
 | ||||||
|  | @ -19,7 +20,7 @@ bootmain(void) | ||||||
|   struct elfhdr *elf; |   struct elfhdr *elf; | ||||||
|   struct proghdr *ph, *eph; |   struct proghdr *ph, *eph; | ||||||
|   void (*entry)(void); |   void (*entry)(void); | ||||||
|   uchar* va; |   uchar* pa; | ||||||
| 
 | 
 | ||||||
|   elf = (struct elfhdr*)0x10000;  // scratch space
 |   elf = (struct elfhdr*)0x10000;  // scratch space
 | ||||||
| 
 | 
 | ||||||
|  | @ -34,15 +35,15 @@ bootmain(void) | ||||||
|   ph = (struct proghdr*)((uchar*)elf + elf->phoff); |   ph = (struct proghdr*)((uchar*)elf + elf->phoff); | ||||||
|   eph = ph + elf->phnum; |   eph = ph + elf->phnum; | ||||||
|   for(; ph < eph; ph++){ |   for(; ph < eph; ph++){ | ||||||
|     va = (uchar*)ph->va; |     pa = (uchar*)ph->pa; | ||||||
|     readseg(va, ph->filesz, ph->offset); |     readseg(pa, ph->filesz, ph->offset); | ||||||
|     if(ph->memsz > ph->filesz) |     if(ph->memsz > ph->filesz) | ||||||
|       stosb(va + ph->filesz, 0, ph->memsz - ph->filesz); |       stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Call the entry point from the ELF header.
 |   // Call the entry point from the ELF header.
 | ||||||
|   // Does not return!
 |   // Does not return!
 | ||||||
|   entry = (void(*)(void))(elf->entry); |   entry = (void(*)(void))(elf->entry & 0xFFFFFF); | ||||||
|   entry(); |   entry(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								bootother.S
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								bootother.S
									
										
									
									
									
								
							|  | @ -1,4 +1,5 @@ | ||||||
| #include "asm.h" | #include "asm.h" | ||||||
|  | #include "memlayout.h" | ||||||
| 
 | 
 | ||||||
| # Each non-boot CPU ("AP") is started up in response to a STARTUP | # Each non-boot CPU ("AP") is started up in response to a STARTUP | ||||||
| # IPI from the boot CPU.  Section B.4.2 of the Multi-Processor | # IPI from the boot CPU.  Section B.4.2 of the Multi-Processor | ||||||
|  | @ -24,6 +25,8 @@ | ||||||
| 
 | 
 | ||||||
| #define CR0_PE    1 | #define CR0_PE    1 | ||||||
| 
 | 
 | ||||||
|  | #define RELOC1(x) ((x) + KERNBASE)    // same as V2P, but without casts | ||||||
|  | 
 | ||||||
| .code16            | .code16            | ||||||
| .globl start
 | .globl start
 | ||||||
| start: | start: | ||||||
|  | @ -40,7 +43,7 @@ start: | ||||||
|   movl    %eax, %cr0 |   movl    %eax, %cr0 | ||||||
| 
 | 
 | ||||||
| //PAGEBREAK! | //PAGEBREAK! | ||||||
|   ljmp    $(SEG_KCODE<<3), $start32 |   ljmpl    $(SEG_KCODE<<3), $(start32+KERNBASE) | ||||||
| 
 | 
 | ||||||
| .code32 | .code32 | ||||||
| start32: | start32: | ||||||
|  | @ -53,10 +56,10 @@ start32: | ||||||
|   movw    %ax, %gs |   movw    %ax, %gs | ||||||
| 
 | 
 | ||||||
|   # switch to the stack allocated by bootothers() |   # switch to the stack allocated by bootothers() | ||||||
|   movl    start-4, %esp |   movl    RELOC1(start-4), %esp | ||||||
| 
 | 
 | ||||||
|   # call mpmain() |   # call mpmain() | ||||||
|   call	*(start-8) |   call	*(RELOC1(start)-8) | ||||||
| 
 | 
 | ||||||
|   movw    $0x8a00, %ax |   movw    $0x8a00, %ax | ||||||
|   movw    %ax, %dx |   movw    %ax, %dx | ||||||
|  | @ -69,8 +72,9 @@ spin: | ||||||
| .p2align 2
 | .p2align 2
 | ||||||
| gdt: | gdt: | ||||||
|   SEG_NULLASM |   SEG_NULLASM | ||||||
|   SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) |   SEG_ASM(STA_X|STA_R, -KERNBASE, 0xffffffff) | ||||||
|   SEG_ASM(STA_W, 0x0, 0xffffffff) |   SEG_ASM(STA_W, -KERNBASE, 0xffffffff) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| gdtdesc: | gdtdesc: | ||||||
|   .word   (gdtdesc - gdt - 1) |   .word   (gdtdesc - gdt - 1) | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| #include "spinlock.h" | #include "spinlock.h" | ||||||
| #include "fs.h" | #include "fs.h" | ||||||
| #include "file.h" | #include "file.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
|  | @ -60,6 +61,9 @@ cprintf(char *fmt, ...) | ||||||
|   if(locking) |   if(locking) | ||||||
|     acquire(&cons.lock); |     acquire(&cons.lock); | ||||||
| 
 | 
 | ||||||
|  |   if (fmt == 0) | ||||||
|  |     panic("null fmt"); | ||||||
|  | 
 | ||||||
|   argp = (uint*)(void*)(&fmt + 1); |   argp = (uint*)(void*)(&fmt + 1); | ||||||
|   state = 0; |   state = 0; | ||||||
|   for(i = 0; (c = fmt[i] & 0xff) != 0; i++){ |   for(i = 0; (c = fmt[i] & 0xff) != 0; i++){ | ||||||
|  | @ -121,7 +125,7 @@ panic(char *s) | ||||||
| //PAGEBREAK: 50
 | //PAGEBREAK: 50
 | ||||||
| #define BACKSPACE 0x100 | #define BACKSPACE 0x100 | ||||||
| #define CRTPORT 0x3d4 | #define CRTPORT 0x3d4 | ||||||
| static ushort *crt = (ushort*)0xb8000;  // CGA memory
 | static ushort *crt = (ushort*)P2V(0xb8000);  // CGA memory
 | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| cgaputc(int c) | cgaputc(int c) | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								defs.h
									
										
									
									
									
								
							|  | @ -62,6 +62,7 @@ extern uchar    ioapicid; | ||||||
| void            ioapicinit(void); | void            ioapicinit(void); | ||||||
| 
 | 
 | ||||||
| // kalloc.c
 | // kalloc.c
 | ||||||
|  | char*           pgalloc(void); | ||||||
| char*           kalloc(void); | char*           kalloc(void); | ||||||
| void            kfree(char*); | void            kfree(char*); | ||||||
| void            kinit(void); | void            kinit(void); | ||||||
|  | @ -160,6 +161,7 @@ void            uartintr(void); | ||||||
| void            uartputc(int); | void            uartputc(int); | ||||||
| 
 | 
 | ||||||
| // vm.c
 | // vm.c
 | ||||||
|  | void            pginit(char* (*alloc)()); | ||||||
| void            seginit(void); | void            seginit(void); | ||||||
| void            kvmalloc(void); | void            kvmalloc(void); | ||||||
| void            vmenable(void); | void            vmenable(void); | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								exec.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								exec.c
									
										
									
									
									
								
							|  | @ -1,5 +1,6 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								ide.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								ide.c
									
										
									
									
									
								
							|  | @ -3,6 +3,7 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								kalloc.c
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								kalloc.c
									
										
									
									
									
								
							|  | @ -5,6 +5,7 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "spinlock.h" | #include "spinlock.h" | ||||||
| 
 | 
 | ||||||
|  | @ -18,6 +19,20 @@ struct { | ||||||
| } kmem; | } kmem; | ||||||
| 
 | 
 | ||||||
| extern char end[]; // first address after kernel loaded from ELF file
 | extern char end[]; // first address after kernel loaded from ELF file
 | ||||||
|  | char *newend; | ||||||
|  | 
 | ||||||
|  | // simple page allocator to get off the ground during boot
 | ||||||
|  | char * | ||||||
|  | pgalloc(void) | ||||||
|  | { | ||||||
|  |   if (newend == 0) | ||||||
|  |     newend = end; | ||||||
|  | 
 | ||||||
|  |   void *p = (void*)PGROUNDUP((uint)newend); | ||||||
|  |   memset(p, 0, PGSIZE); | ||||||
|  |   newend = newend + PGSIZE; | ||||||
|  |   return p; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| // Initialize free list of physical pages.
 | // Initialize free list of physical pages.
 | ||||||
| void | void | ||||||
|  | @ -26,8 +41,8 @@ kinit(void) | ||||||
|   char *p; |   char *p; | ||||||
| 
 | 
 | ||||||
|   initlock(&kmem.lock, "kmem"); |   initlock(&kmem.lock, "kmem"); | ||||||
|   p = (char*)PGROUNDUP((uint)end); |   p = (char*)PGROUNDUP((uint)newend); | ||||||
|   for(; p + PGSIZE <= (char*)PHYSTOP; p += PGSIZE) |   for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE) | ||||||
|     kfree(p); |     kfree(p); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -41,7 +56,7 @@ kfree(char *v) | ||||||
| { | { | ||||||
|   struct run *r; |   struct run *r; | ||||||
| 
 | 
 | ||||||
|   if((uint)v % PGSIZE || v < end || (uint)v >= PHYSTOP)  |   if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP)  | ||||||
|     panic("kfree"); |     panic("kfree"); | ||||||
| 
 | 
 | ||||||
|   // Fill with junk to catch dangling refs.
 |   // Fill with junk to catch dangling refs.
 | ||||||
|  | @ -67,6 +82,7 @@ kalloc(void) | ||||||
|   if(r) |   if(r) | ||||||
|     kmem.freelist = r->next; |     kmem.freelist = r->next; | ||||||
|   release(&kmem.lock); |   release(&kmem.lock); | ||||||
|  |   cprintf("kalloc: 0x%x\n", r); | ||||||
|   return (char*)r; |   return (char*)r; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								main.c
									
										
									
									
									
								
							|  | @ -1,6 +1,7 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
|  | @ -9,6 +10,8 @@ static void bootothers(void); | ||||||
| static void mpmain(void); | static void mpmain(void); | ||||||
| void jmpkstack(void)  __attribute__((noreturn)); | void jmpkstack(void)  __attribute__((noreturn)); | ||||||
| void mainc(void); | void mainc(void); | ||||||
|  | static volatile int newpgdir; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| // Bootstrap processor starts running C code here.
 | // Bootstrap processor starts running C code here.
 | ||||||
| // Allocate a real stack and switch to it, first
 | // Allocate a real stack and switch to it, first
 | ||||||
|  | @ -16,6 +19,7 @@ void mainc(void); | ||||||
| int | int | ||||||
| main(void) | main(void) | ||||||
| { | { | ||||||
|  |   pginit(pgalloc); | ||||||
|   mpinit();        // collect info about this machine
 |   mpinit();        // collect info about this machine
 | ||||||
|   lapicinit(mpbcpu()); |   lapicinit(mpbcpu()); | ||||||
|   seginit();       // set up segments
 |   seginit();       // set up segments
 | ||||||
|  | @ -46,7 +50,6 @@ mainc(void) | ||||||
|   ioapicinit();    // another interrupt controller
 |   ioapicinit();    // another interrupt controller
 | ||||||
|   consoleinit();   // I/O devices & their interrupts
 |   consoleinit();   // I/O devices & their interrupts
 | ||||||
|   uartinit();      // serial port
 |   uartinit();      // serial port
 | ||||||
|   kvmalloc();      // initialize the kernel page table
 |  | ||||||
|   pinit();         // process table
 |   pinit();         // process table
 | ||||||
|   tvinit();        // trap vectors
 |   tvinit();        // trap vectors
 | ||||||
|   binit();         // buffer cache
 |   binit();         // buffer cache
 | ||||||
|  | @ -57,25 +60,35 @@ mainc(void) | ||||||
|     timerinit();   // uniprocessor timer
 |     timerinit();   // uniprocessor timer
 | ||||||
|   userinit();      // first user process
 |   userinit();      // first user process
 | ||||||
|   bootothers();    // start other processors
 |   bootothers();    // start other processors
 | ||||||
| 
 |   kvmalloc();      // new kernel page table wo. bottom mapped
 | ||||||
|  |   newpgdir = 1; | ||||||
|   // Finish setting up this processor in mpmain.
 |   // Finish setting up this processor in mpmain.
 | ||||||
|   mpmain(); |   mpmain(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Common CPU setup code.
 | ||||||
|  | // Bootstrap CPU comes here from mainc().
 | ||||||
|  | // Other CPUs jump here from bootother.S.
 | ||||||
|  | static void | ||||||
|  | mpboot(void) | ||||||
|  | { | ||||||
|  |   vmenable();        // turn on paging
 | ||||||
|  |   seginit(); | ||||||
|  |   lapicinit(cpunum()); | ||||||
|  |   mpmain(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Common CPU setup code.
 | // Common CPU setup code.
 | ||||||
| // Bootstrap CPU comes here from mainc().
 | // Bootstrap CPU comes here from mainc().
 | ||||||
| // Other CPUs jump here from bootother.S.
 | // Other CPUs jump here from bootother.S.
 | ||||||
| static void | static void | ||||||
| mpmain(void) | mpmain(void) | ||||||
| { | { | ||||||
|   if(cpunum() != mpbcpu()){ |  | ||||||
|     seginit(); |  | ||||||
|     lapicinit(cpunum()); |  | ||||||
|   } |  | ||||||
|   vmenable();        // turn on paging
 |  | ||||||
|   cprintf("cpu%d: starting\n", cpu->id); |   cprintf("cpu%d: starting\n", cpu->id); | ||||||
|   idtinit();       // load idt register
 |   idtinit();       // load idt register
 | ||||||
|   xchg(&cpu->booted, 1); // tell bootothers() we're up
 |   xchg(&cpu->booted, 1); // tell bootothers() we're up
 | ||||||
|  |   while (!newpgdir) ;  // wait until we have new page dir
 | ||||||
|  |   switchkvm();     // switch to new page dir
 | ||||||
|   scheduler();     // start running processes
 |   scheduler();     // start running processes
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -91,7 +104,7 @@ bootothers(void) | ||||||
|   // Write bootstrap code to unused memory at 0x7000.
 |   // Write bootstrap code to unused memory at 0x7000.
 | ||||||
|   // The linker has placed the image of bootother.S in
 |   // The linker has placed the image of bootother.S in
 | ||||||
|   // _binary_bootother_start.
 |   // _binary_bootother_start.
 | ||||||
|   code = (uchar*)0x7000; |   code = p2v(0x7000); | ||||||
|   memmove(code, _binary_bootother_start, (uint)_binary_bootother_size); |   memmove(code, _binary_bootother_start, (uint)_binary_bootother_size); | ||||||
| 
 | 
 | ||||||
|   for(c = cpus; c < cpus+ncpu; c++){ |   for(c = cpus; c < cpus+ncpu; c++){ | ||||||
|  | @ -103,9 +116,9 @@ bootothers(void) | ||||||
|     // its first instruction.
 |     // its first instruction.
 | ||||||
|     stack = kalloc(); |     stack = kalloc(); | ||||||
|     *(void**)(code-4) = stack + KSTACKSIZE; |     *(void**)(code-4) = stack + KSTACKSIZE; | ||||||
|     *(void**)(code-8) = mpmain; |     *(void**)(code-8) = mpboot; | ||||||
| 
 | 
 | ||||||
|     lapicstartap(c->id, (uint)code); |     lapicstartap(c->id, v2p(code)); | ||||||
| 
 | 
 | ||||||
|     // Wait for cpu to finish mpmain()
 |     // Wait for cpu to finish mpmain()
 | ||||||
|     while(c->booted == 0) |     while(c->booted == 0) | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								mmu.h
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								mmu.h
									
										
									
									
									
								
							|  | @ -106,18 +106,10 @@ struct segdesc { | ||||||
| // construct linear address from indexes and offset
 | // construct linear address from indexes and offset
 | ||||||
| #define PGADDR(d, t, o)	((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o))) | #define PGADDR(d, t, o)	((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o))) | ||||||
| 
 | 
 | ||||||
| // turn a kernel linear address into a physical address.
 |  | ||||||
| // all of the kernel data structures have linear and
 |  | ||||||
| // physical addresses that are equal.
 |  | ||||||
| #define PADDR(a)       ((uint)(a)) |  | ||||||
| 
 |  | ||||||
| // Page directory and page table constants.
 | // Page directory and page table constants.
 | ||||||
| #define NPDENTRIES	1024		// page directory entries per page directory
 | #define NPDENTRIES	1024		// page directory entries per page directory
 | ||||||
| #define NPTENTRIES	1024		// page table entries per page table
 | #define NPTENTRIES	1024		// page table entries per page table
 | ||||||
| 
 | 
 | ||||||
| #define PGSIZE		4096		// bytes mapped by a page
 |  | ||||||
| #define PGSHIFT		12		// log2(PGSIZE)
 |  | ||||||
| 
 |  | ||||||
| #define PTXSHIFT	12		// offset of PTX in a linear address
 | #define PTXSHIFT	12		// offset of PTX in a linear address
 | ||||||
| #define PDXSHIFT	22		// offset of PDX in a linear address
 | #define PDXSHIFT	22		// offset of PDX in a linear address
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								mp.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								mp.c
									
										
									
									
									
								
							|  | @ -5,6 +5,7 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mp.h" | #include "mp.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
|  | @ -39,6 +40,7 @@ mpsearch1(uchar *addr, int len) | ||||||
| { | { | ||||||
|   uchar *e, *p; |   uchar *e, *p; | ||||||
| 
 | 
 | ||||||
|  |   addr = p2v((uint) addr); | ||||||
|   e = addr+len; |   e = addr+len; | ||||||
|   for(p = addr; p < e; p += sizeof(struct mp)) |   for(p = addr; p < e; p += sizeof(struct mp)) | ||||||
|     if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0) |     if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0) | ||||||
|  | @ -83,7 +85,7 @@ mpconfig(struct mp **pmp) | ||||||
| 
 | 
 | ||||||
|   if((mp = mpsearch()) == 0 || mp->physaddr == 0) |   if((mp = mpsearch()) == 0 || mp->physaddr == 0) | ||||||
|     return 0; |     return 0; | ||||||
|   conf = (struct mpconf*)mp->physaddr; |   conf = (struct mpconf*) p2v((uint) mp->physaddr); | ||||||
|   if(memcmp(conf, "PCMP", 4) != 0) |   if(memcmp(conf, "PCMP", 4) != 0) | ||||||
|     return 0; |     return 0; | ||||||
|   if(conf->version != 1 && conf->version != 4) |   if(conf->version != 1 && conf->version != 4) | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								multiboot.S
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								multiboot.S
									
										
									
									
									
								
							|  | @ -15,6 +15,9 @@ | ||||||
| # } | # } | ||||||
| 
 | 
 | ||||||
| #include "asm.h" | #include "asm.h" | ||||||
|  | #include "memlayout.h" | ||||||
|  | 
 | ||||||
|  | #define RELOC(x) ((x) - KERNBASE)    // same as V2P, but without casts | ||||||
| 
 | 
 | ||||||
| #define STACK 4096 | #define STACK 4096 | ||||||
| 
 | 
 | ||||||
|  | @ -42,7 +45,7 @@ multiboot_header: | ||||||
| # boot loader - bootasm.S - sets up. | # boot loader - bootasm.S - sets up. | ||||||
| .globl multiboot_entry
 | .globl multiboot_entry
 | ||||||
| multiboot_entry: | multiboot_entry: | ||||||
|   lgdt gdtdesc |   lgdt RELOC(gdtdesc) | ||||||
|   ljmp $(SEG_KCODE<<3), $mbstart32 |   ljmp $(SEG_KCODE<<3), $mbstart32 | ||||||
| 
 | 
 | ||||||
| mbstart32: | mbstart32: | ||||||
|  | @ -65,11 +68,11 @@ spin: | ||||||
| .p2align 2                                # force 4 byte alignment | .p2align 2                                # force 4 byte alignment | ||||||
| gdt: | gdt: | ||||||
|   SEG_NULLASM                             # null seg |   SEG_NULLASM                             # null seg | ||||||
|   SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # code seg |   SEG_ASM(STA_X|STA_R, -KERNBASE, 0xffffffff)   # code seg | ||||||
|   SEG_ASM(STA_W, 0x0, 0xffffffff)         # data seg |   SEG_ASM(STA_W, -KERNBASE, 0xffffffff)         # data seg | ||||||
| 
 | 
 | ||||||
| gdtdesc: | gdtdesc: | ||||||
|   .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1 |   .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1 | ||||||
|   .long   gdt                             # address gdt |   .long   RELOC(gdt)                      # address gdt | ||||||
| 
 | 
 | ||||||
| .comm stack, STACK | .comm stack, STACK | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								param.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								param.h
									
										
									
									
									
								
							|  | @ -7,8 +7,6 @@ | ||||||
| #define NINODE       50  // maximum number of active i-nodes
 | #define NINODE       50  // maximum number of active i-nodes
 | ||||||
| #define NDEV         10  // maximum major device number
 | #define NDEV         10  // maximum major device number
 | ||||||
| #define ROOTDEV       1  // device number of file system root disk
 | #define ROOTDEV       1  // device number of file system root disk
 | ||||||
| #define USERTOP  0xA0000 // end of user address space
 |  | ||||||
| #define PHYSTOP  0x1000000 // use phys mem up to here as free pool
 |  | ||||||
| #define MAXARG       32  // max exec arguments
 | #define MAXARG       32  // max exec arguments
 | ||||||
| #define LOGSIZE      10  // size of log
 | #define LOGSIZE      10  // size of log
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								proc.c
									
										
									
									
									
								
							|  | @ -1,6 +1,7 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| #include "spinlock.h" | #include "spinlock.h" | ||||||
|  | @ -71,7 +72,7 @@ getcallerpcs(void *v, uint pcs[]) | ||||||
|    |    | ||||||
|   ebp = (uint*)v - 2; |   ebp = (uint*)v - 2; | ||||||
|   for(i = 0; i < 10; i++){ |   for(i = 0; i < 10; i++){ | ||||||
|     if(ebp == 0 || ebp < (uint*)0x100000 || ebp == (uint*)0xffffffff) |     if(ebp == 0 || ebp < (uint*)KERNBASE || ebp == (uint*)0xffffffff) | ||||||
|       break; |       break; | ||||||
|     pcs[i] = ebp[1];     // saved %eip
 |     pcs[i] = ebp[1];     // saved %eip
 | ||||||
|     ebp = (uint*)ebp[0]; // saved %ebp
 |     ebp = (uint*)ebp[0]; // saved %ebp
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								trap.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								trap.c
									
										
									
									
									
								
							|  | @ -1,6 +1,7 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
|  |  | ||||||
							
								
								
									
										129
									
								
								vm.c
									
										
									
									
									
								
							
							
						
						
									
										129
									
								
								vm.c
									
										
									
									
									
								
							|  | @ -2,20 +2,71 @@ | ||||||
| #include "types.h" | #include "types.h" | ||||||
| #include "defs.h" | #include "defs.h" | ||||||
| #include "x86.h" | #include "x86.h" | ||||||
|  | #include "memlayout.h" | ||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #include "proc.h" | #include "proc.h" | ||||||
| #include "elf.h" | #include "elf.h" | ||||||
| 
 | 
 | ||||||
| extern char data[];  // defined in data.S
 | extern char data[];  // defined in data.S
 | ||||||
| 
 |  | ||||||
| static pde_t *kpgdir;  // for use in scheduler()
 | static pde_t *kpgdir;  // for use in scheduler()
 | ||||||
|  | struct segdesc gdt[NSEGS]; | ||||||
| 
 | 
 | ||||||
| // Allocate one page table for the machine for the kernel address
 | 
 | ||||||
| // space for scheduler processes.
 | // page map for during boot
 | ||||||
| void | // XXX build a static page table in assembly
 | ||||||
| kvmalloc(void) | static void | ||||||
|  | pgmap(void *va, void *last, uint pa) | ||||||
| { | { | ||||||
|   kpgdir = setupkvm(); |   pde_t *pde; | ||||||
|  |   pte_t *pgtab; | ||||||
|  |   pte_t *pte; | ||||||
|  | 
 | ||||||
|  |   for(;;){ | ||||||
|  |     pde = &kpgdir[PDX(va)]; | ||||||
|  |     pde_t pdev = *pde; | ||||||
|  |     if (pdev == 0) { | ||||||
|  |       pgtab = (pte_t *) pgalloc(); | ||||||
|  |       *pde = v2p(pgtab) | PTE_P | PTE_W; | ||||||
|  |     } else { | ||||||
|  |       pgtab = (pte_t*)p2v(PTE_ADDR(pdev)); | ||||||
|  |     } | ||||||
|  |     pte = &pgtab[PTX(va)]; | ||||||
|  |     *pte = pa | PTE_W | PTE_P; | ||||||
|  |     if(va == last) | ||||||
|  |       break; | ||||||
|  |     va += PGSIZE; | ||||||
|  |     pa += PGSIZE; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // set up a page table to get off the ground
 | ||||||
|  | void | ||||||
|  | pginit(char* (*alloc)(void)) | ||||||
|  | { | ||||||
|  |   uint cr0; | ||||||
|  | 
 | ||||||
|  |   kpgdir = (pde_t *) alloc(); | ||||||
|  |   pgmap((void *) 0, (void *) PHYSTOP, 0);    // map pa 0 at va 0
 | ||||||
|  |   pgmap((void *) KERNBASE, (void *) (KERNBASE+PHYSTOP), 0);   // map pa 0 at va KERNBASE
 | ||||||
|  |   pgmap((void*)0xFE000000, 0, 0xFE000000); | ||||||
|  | 
 | ||||||
|  |   switchkvm(); // load kpgdir into cr3
 | ||||||
|  | 
 | ||||||
|  |   cr0 = rcr0(); | ||||||
|  |   cr0 |= CR0_PG; | ||||||
|  |   lcr0(cr0);   // paging on
 | ||||||
|  | 
 | ||||||
|  |   // new gdt
 | ||||||
|  |   gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0); | ||||||
|  |   gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); | ||||||
|  |   lgdt((void *)v2p(gdt), sizeof(gdt)); | ||||||
|  |   loadgs(SEG_KDATA << 3); | ||||||
|  |   loadfs(SEG_KDATA << 3); | ||||||
|  |   loades(SEG_KDATA << 3); | ||||||
|  |   loadds(SEG_KDATA << 3); | ||||||
|  |   loadss(SEG_KDATA << 3); | ||||||
|  | 
 | ||||||
|  |   __asm volatile("ljmp %0,$1f\n 1:\n" :: "i" (SEG_KCODE << 3));  // reload cs
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Set up CPU's kernel segment descriptors.
 | // Set up CPU's kernel segment descriptors.
 | ||||||
|  | @ -57,7 +108,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create) | ||||||
| 
 | 
 | ||||||
|   pde = &pgdir[PDX(va)]; |   pde = &pgdir[PDX(va)]; | ||||||
|   if(*pde & PTE_P){ |   if(*pde & PTE_P){ | ||||||
|     pgtab = (pte_t*)PTE_ADDR(*pde); |     pgtab = (pte_t*)p2v(PTE_ADDR(*pde)); | ||||||
|   } else { |   } else { | ||||||
|     if(!create || (pgtab = (pte_t*)kalloc()) == 0) |     if(!create || (pgtab = (pte_t*)kalloc()) == 0) | ||||||
|       return 0; |       return 0; | ||||||
|  | @ -66,7 +117,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create) | ||||||
|     // The permissions here are overly generous, but they can
 |     // The permissions here are overly generous, but they can
 | ||||||
|     // be further restricted by the permissions in the page table 
 |     // be further restricted by the permissions in the page table 
 | ||||||
|     // entries, if necessary.
 |     // entries, if necessary.
 | ||||||
|     *pde = PADDR(pgtab) | PTE_P | PTE_W | PTE_U; |     *pde = v2p(pgtab) | PTE_P | PTE_W | PTE_U; | ||||||
|   } |   } | ||||||
|   return &pgtab[PTX(va)]; |   return &pgtab[PTX(va)]; | ||||||
| } | } | ||||||
|  | @ -105,29 +156,30 @@ mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm) | ||||||
| // page protection bits prevent it from using anything other
 | // page protection bits prevent it from using anything other
 | ||||||
| // than its memory.
 | // than its memory.
 | ||||||
| // 
 | // 
 | ||||||
|  | //
 | ||||||
| // setupkvm() and exec() set up every page table like this:
 | // setupkvm() and exec() set up every page table like this:
 | ||||||
| //   0..640K          : user memory (text, data, stack, heap)
 | //   0..KERNBASE      : user memory (text, data, stack, heap), mapped to some phys mem
 | ||||||
| //   640K..1M         : mapped direct (for IO space)
 | //   KERNBASE+640K..KERNBASE+1M: mapped to 640K..1M
 | ||||||
| //   1M..end          : mapped direct (for the kernel's text and data)
 | //   KERNBASE+1M..KERNBASE+end : mapped to 1M..end
 | ||||||
| //   end..PHYSTOP     : mapped direct (kernel heap and user pages)
 | //   KERNBASE+end..KERBASE+PHYSTOP     : mapped to end..PHYSTOP (free memory)
 | ||||||
| //   0xfe000000..0    : mapped direct (devices such as ioapic)
 | //   0xfe000000..0    : mapped direct (devices such as ioapic)
 | ||||||
| //
 | //
 | ||||||
| // The kernel allocates memory for its heap and for user memory
 | // The kernel allocates memory for its heap and for user memory
 | ||||||
| // between kernend and the end of physical memory (PHYSTOP).
 | // between kernend and the end of physical memory (PHYSTOP).
 | ||||||
| // The virtual address space of each user program includes the kernel
 | // The virtual address space of each user program includes the kernel
 | ||||||
| // (which is inaccessible in user mode).  The user program addresses
 | // (which is inaccessible in user mode).  The user program sits in
 | ||||||
| // range from 0 till 640KB (USERTOP), which where the I/O hole starts
 | // the bottom of the address space, and the kernel at the top at KERNBASE.
 | ||||||
| // (both in physical memory and in the kernel's virtual address
 |  | ||||||
| // space).
 |  | ||||||
| static struct kmap { | static struct kmap { | ||||||
|   void *p; |   void *l; | ||||||
|   void *e; |   uint p; | ||||||
|  |   uint e; | ||||||
|   int perm; |   int perm; | ||||||
| } kmap[] = { | } kmap[] = { | ||||||
|   {(void*)USERTOP,    (void*)0x100000, PTE_W},  // I/O space
 |   { (void *)IOSPACEB, IOSPACEB, IOSPACEE, PTE_W},  // I/O space
 | ||||||
|   {(void*)0x100000,   data,            0    },  // kernel text, rodata
 |   { P2V(IOSPACEB), IOSPACEB, IOSPACEE, PTE_W},  // I/O space
 | ||||||
|   {data,              (void*)PHYSTOP,  PTE_W},  // kernel data, memory
 |   { (void *)KERNLINK, V2P(KERNLINK), V2P(data),  0},  // kernel text, rodata
 | ||||||
|   {(void*)0xFE000000, 0,               PTE_W},  // device mappings
 |   { data, V2P(data), PHYSTOP,  PTE_W},  // kernel data, memory
 | ||||||
|  |   { (void*)0xFE000000, 0xFE000000, 0, PTE_W},  // device mappings
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Set up kernel part of a page table.
 | // Set up kernel part of a page table.
 | ||||||
|  | @ -142,12 +194,21 @@ setupkvm(void) | ||||||
|   memset(pgdir, 0, PGSIZE); |   memset(pgdir, 0, PGSIZE); | ||||||
|   k = kmap; |   k = kmap; | ||||||
|   for(k = kmap; k < &kmap[NELEM(kmap)]; k++) |   for(k = kmap; k < &kmap[NELEM(kmap)]; k++) | ||||||
|     if(mappages(pgdir, k->p, k->e - k->p, (uint)k->p, k->perm) < 0) |     if(mappages(pgdir, k->l, k->e - k->p, (uint)k->p, k->perm) < 0) | ||||||
|       return 0; |       return 0; | ||||||
| 
 | 
 | ||||||
|   return pgdir; |   return pgdir; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Allocate one page table for the machine for the kernel address
 | ||||||
|  | // space for scheduler processes.
 | ||||||
|  | void | ||||||
|  | kvmalloc(void) | ||||||
|  | { | ||||||
|  |   kpgdir = setupkvm(); | ||||||
|  |   switchkvm(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Turn on paging.
 | // Turn on paging.
 | ||||||
| void | void | ||||||
| vmenable(void) | vmenable(void) | ||||||
|  | @ -158,6 +219,16 @@ vmenable(void) | ||||||
|   cr0 = rcr0(); |   cr0 = rcr0(); | ||||||
|   cr0 |= CR0_PG; |   cr0 |= CR0_PG; | ||||||
|   lcr0(cr0); |   lcr0(cr0); | ||||||
|  | 
 | ||||||
|  |  struct cpu *c = &cpus[0]; | ||||||
|  |   lgdt((void *)v2p((void *)(c->gdt)), sizeof(c->gdt)); | ||||||
|  |   loadgs(SEG_KCPU << 3); | ||||||
|  |   loadfs(SEG_KDATA << 3); | ||||||
|  |   loades(SEG_KDATA << 3); | ||||||
|  |   loadds(SEG_KDATA << 3); | ||||||
|  |   loadss(SEG_KDATA << 3); | ||||||
|  | 
 | ||||||
|  |   __asm volatile("ljmp %0,$1f\n 1:\n" :: "i" (SEG_KCODE << 3));  // reload cs
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Switch h/w page table register to the kernel-only page table,
 | // Switch h/w page table register to the kernel-only page table,
 | ||||||
|  | @ -165,7 +236,7 @@ vmenable(void) | ||||||
| void | void | ||||||
| switchkvm(void) | switchkvm(void) | ||||||
| { | { | ||||||
|   lcr3(PADDR(kpgdir));   // switch to the kernel page table
 |   lcr3(v2p(kpgdir));   // switch to the kernel page table
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Switch TSS and h/w page table to correspond to process p.
 | // Switch TSS and h/w page table to correspond to process p.
 | ||||||
|  | @ -180,7 +251,7 @@ switchuvm(struct proc *p) | ||||||
|   ltr(SEG_TSS << 3); |   ltr(SEG_TSS << 3); | ||||||
|   if(p->pgdir == 0) |   if(p->pgdir == 0) | ||||||
|     panic("switchuvm: no pgdir"); |     panic("switchuvm: no pgdir"); | ||||||
|   lcr3(PADDR(p->pgdir));  // switch to new address space
 |   lcr3(v2p(p->pgdir));  // switch to new address space
 | ||||||
|   popcli(); |   popcli(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -195,7 +266,7 @@ inituvm(pde_t *pgdir, char *init, uint sz) | ||||||
|     panic("inituvm: more than a page"); |     panic("inituvm: more than a page"); | ||||||
|   mem = kalloc(); |   mem = kalloc(); | ||||||
|   memset(mem, 0, PGSIZE); |   memset(mem, 0, PGSIZE); | ||||||
|   mappages(pgdir, 0, PGSIZE, PADDR(mem), PTE_W|PTE_U); |   mappages(pgdir, 0, PGSIZE, v2p(mem), PTE_W|PTE_U); | ||||||
|   memmove(mem, init, sz); |   memmove(mem, init, sz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -245,7 +316,7 @@ allocuvm(pde_t *pgdir, uint oldsz, uint newsz) | ||||||
|       return 0; |       return 0; | ||||||
|     } |     } | ||||||
|     memset(mem, 0, PGSIZE); |     memset(mem, 0, PGSIZE); | ||||||
|     mappages(pgdir, (char*)a, PGSIZE, PADDR(mem), PTE_W|PTE_U); |     mappages(pgdir, (char*)a, PGSIZE, v2p(mem), PTE_W|PTE_U); | ||||||
|   } |   } | ||||||
|   return newsz; |   return newsz; | ||||||
| } | } | ||||||
|  | @ -289,7 +360,7 @@ freevm(pde_t *pgdir) | ||||||
|   deallocuvm(pgdir, USERTOP, 0); |   deallocuvm(pgdir, USERTOP, 0); | ||||||
|   for(i = 0; i < NPDENTRIES; i++){ |   for(i = 0; i < NPDENTRIES; i++){ | ||||||
|     if(pgdir[i] & PTE_P) |     if(pgdir[i] & PTE_P) | ||||||
|       kfree((char*)PTE_ADDR(pgdir[i])); |       kfree(p2v(PTE_ADDR(pgdir[i]))); | ||||||
|   } |   } | ||||||
|   kfree((char*)pgdir); |   kfree((char*)pgdir); | ||||||
| } | } | ||||||
|  | @ -315,7 +386,7 @@ copyuvm(pde_t *pgdir, uint sz) | ||||||
|     if((mem = kalloc()) == 0) |     if((mem = kalloc()) == 0) | ||||||
|       goto bad; |       goto bad; | ||||||
|     memmove(mem, (char*)pa, PGSIZE); |     memmove(mem, (char*)pa, PGSIZE); | ||||||
|     if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) |     if(mappages(d, (void*)i, PGSIZE, v2p(mem), PTE_W|PTE_U) < 0) | ||||||
|       goto bad; |       goto bad; | ||||||
|   } |   } | ||||||
|   return d; |   return d; | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								x86.h
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								x86.h
									
										
									
									
									
								
							|  | @ -96,6 +96,30 @@ loadgs(ushort v) | ||||||
|   asm volatile("movw %0, %%gs" : : "r" (v)); |   asm volatile("movw %0, %%gs" : : "r" (v)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline void | ||||||
|  | loadfs(ushort v) | ||||||
|  | { | ||||||
|  |   __asm volatile("movw %0, %%fs" : : "r" (v)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | loades(ushort v) | ||||||
|  | { | ||||||
|  |   __asm volatile("movw %0, %%es" : : "r" (v)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | loadds(ushort v) | ||||||
|  | { | ||||||
|  |   __asm volatile("movw %0, %%ds" : : "r" (v)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | loadss(ushort v) | ||||||
|  | { | ||||||
|  |   __asm volatile("movw %0, %%ss" : : "r" (v)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static inline uint | static inline uint | ||||||
| rebp(void) | rebp(void) | ||||||
| { | { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Frans Kaashoek
						Frans Kaashoek