#include "asm.h"
-#include "memlayout.h"
#include "mmu.h"
# Start the first CPU: switch to 32-bit protected mode, jump into C.
movw %ax,%es # -> Extra Segment
movw %ax,%ss # -> Stack Segment
- # Physical address line A20 is tied to zero so that the first PCs
+ # Physical address line A20 is tied to zero so that the first PCs
# with 2 MB would run software that assumed 1 MB. Undo that.
seta20.1:
inb $0x64,%al # Wait for not busy
#include "types.h"
#include "elf.h"
#include "x86.h"
-#include "memlayout.h"
#include "ide.h"
void readseg(uchar*, uint, uint);
movl %eax, %cr0
# Set up the stack pointer.
- movl $(stack + KSTACKSIZE), %esp
+ movl $(stack + KSTACKSIZE), %esp
- # Jump to main(), and switch to executing at
- # high addresses. The indirect call is needed because
- # the assembler produces a PC-relative instruction
- # for a direct jump.
- mov $main, %eax
- jmp *%eax
+ # Jump to main() and switch to executing at high addresses.
+ # Need an explicit long jump (indirect jump would work as
+ # well, as would a push/ret trick to save 1 byte) because
+ # the assembler produces a PC-relative instruction for a
+ # direct jump.
+ ljmp $(SEG_KCODE<<3), $main
.comm stack, KSTACKSIZE
#include "asm.h"
-#include "memlayout.h"
#include "mmu.h"
-
+
# 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
# Specification says that the AP will start in real mode with CS:IP
# - it does not need to enable A20
# - it uses the address at start-4, start-8, and start-12
-.code16
+.code16
.globl start
start:
- cli
+ cli
xorw %ax,%ax
movw %ax,%ds
movl %eax, %cr0
//PAGEBREAK!
- ljmpl $(SEG_KCODE<<3), $(start32)
+ ljmp $(SEG_KCODE<<3), $start32
.code32
start32:
movl %eax, %cr3
# Turn on paging.
movl %cr0, %eax
- orl $(CR0_PE|CR0_PG|CR0_WP), %eax
+ orl $(CR0_PG|CR0_WP), %eax
movl %eax, %cr0
# Switch to the stack allocated by startothers()
movl (start-4), %esp
# Call mpenter()
- call *(start-8)
+ call *(start-8)
movw $0x8a00, %ax
movw %ax, %dx
SEG_ASM(STA_X|STA_R, 0, 0xffffffff)
SEG_ASM(STA_W, 0, 0xffffffff)
-
gdtdesc:
.word (gdtdesc - gdt - 1)
.long gdt
#include "types.h"
#include "param.h"
-#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "defs.h"
#include "types.h"
#include "defs.h"
#include "param.h"
-#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
{
struct run *r;
- if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP)
+ if((uint)v % PGSIZE || v < end || V2P(v) >= PHYSTOP)
panic("kfree");
// Fill with junk to catch dangling refs.
static void startothers(void);
static void mpmain(void) __attribute__((noreturn));
-extern pde_t *kpgdir;
extern char end[]; // first address after kernel loaded from ELF file
// Bootstrap processor starts running C code here.
static void
mpenter(void)
{
- switchkvm();
+ switchkvm();
seginit();
lapicinit();
mpmain();
// Write entry code to unused memory at 0x7000.
// The linker has placed the image of entryother.S in
// _binary_entryother_start.
- code = p2v(0x7000);
+ code = P2V(0x7000);
memmove(code, _binary_entryother_start, (uint)_binary_entryother_size);
for(c = cpus; c < cpus+ncpu; c++){
if(c == cpus+cpunum()) // We've started already.
continue;
- // Tell entryother.S what stack to use, where to enter, and what
+ // Tell entryother.S what stack to use, where to enter, and what
// pgdir to use. We cannot use kpgdir yet, because the AP processor
// is running in low memory, so we use entrypgdir for the APs too.
stack = kalloc();
*(void**)(code-4) = stack + KSTACKSIZE;
*(void**)(code-8) = mpenter;
- *(int**)(code-12) = (void *) v2p(entrypgdir);
+ *(int**)(code-12) = (void *) V2P(entrypgdir);
- lapicstartap(c->id, v2p(code));
+ lapicstartap(c->id, V2P(code));
// wait for cpu to finish mpmain()
while(c->started == 0)
// Boot page table used in entry.S and entryother.S.
// Page directories (and page tables), must start on a page boundary,
-// hence the "__aligned__" attribute.
+// hence the "__aligned__" attribute.
// Use PTE_PS in page directory entry to enable 4Mbyte pages.
__attribute__((__aligned__(PGSIZE)))
pde_t entrypgdir[NPDENTRIES] = {
// Memory layout
-#define EXTMEM 0x100000 // Start of extended memory
-#define PHYSTOP 0xE000000 // Top physical memory
+#define EXTMEM 0x100000 // Start of extended memory, 1 MB
+#define PHYSTOP 0xE000000 // Top physical memory, 224 MB
#define DEVSPACE 0xFE000000 // Other devices are at high addresses
// Key addresses for address space layout (see kmap in vm.c for layout)
#ifndef __ASSEMBLER__
-static inline uint v2p(void *a) { return ((uint) (a)) - KERNBASE; }
-static inline void *p2v(uint a) { return (void *) ((a) + KERNBASE); }
-
-#endif
-
+// Convert virtual and physical addresses (from kernel's perspective)
#define V2P(a) (((uint) (a)) - KERNBASE)
#define P2V(a) (((void *) (a)) + KERNBASE)
-#define V2P_WO(x) ((x) - KERNBASE) // same as V2P, but without casts
-#define P2V_WO(x) ((x) + KERNBASE) // same as V2P, but without casts
+#else
+
+// The same without casts (for use in assembly)
+#define V2P_WO(x) ((x) - KERNBASE)
+#define P2V_WO(x) ((x) + KERNBASE)
+
+#endif
{
uchar *e, *p, *addr;
- addr = p2v(a);
+ addr = P2V(a);
e = addr+len;
for(p = addr; p < e; p += sizeof(struct mp))
if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
if((mp = mpsearch()) == 0 || mp->physaddr == 0)
return 0;
- conf = (struct mpconf*) p2v((uint) mp->physaddr);
+ conf = (struct mpconf*) P2V((uint) mp->physaddr);
if(memcmp(conf, "PCMP", 4) != 0)
return 0;
if(conf->version != 1 && conf->version != 4)
#include "types.h"
#include "defs.h"
#include "param.h"
-#include "memlayout.h"
#include "mmu.h"
#include "x86.h"
#include "proc.h"
return 0;
}
sp = p->kstack + KSTACKSIZE;
-
+
// Leave room for trap frame.
sp -= sizeof *p->tf;
p->tf = (struct trapframe*)sp;
-
+
// Set up new context to start executing at forkret,
// which returns to trapret.
sp -= 4;
{
struct proc *p;
extern char _binary_initcode_start[], _binary_initcode_size[];
-
+
p = allocproc();
initproc = p;
if((p->pgdir = setupkvm()) == 0)
growproc(int n)
{
uint sz;
-
+
sz = proc->sz;
if(n > 0){
if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0)
np->cwd = idup(proc->cwd);
safestrcpy(np->name, proc->name, sizeof(proc->name));
-
+
pid = np->pid;
// lock to force the compiler to emit the np->state write last.
acquire(&ptable.lock);
np->state = RUNNABLE;
release(&ptable.lock);
-
+
return pid;
}
if (first) {
// Some initialization functions must be run in the context
- // of a regular process (e.g., they call sleep), and thus cannot
+ // of a regular process (e.g., they call sleep), and thus cannot
// be run from main().
first = 0;
iinit(ROOTDEV);
initlog(ROOTDEV);
}
-
+
// Return to "caller", actually trapret (see allocproc).
}
struct proc *p;
char *state;
uint pc[10];
-
+
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->state == UNUSED)
continue;
#include "types.h"
#include "defs.h"
#include "param.h"
-#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
argptr(int n, char **pp, int size)
{
int i;
-
+
if(argint(n, &i) < 0)
return -1;
if((uint)i >= proc->sz || (uint)i+size > proc->sz)
#include "defs.h"
#include "date.h"
#include "param.h"
-#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
{
int n;
uint ticks0;
-
+
if(argint(0, &n) < 0)
return -1;
acquire(&tickslock);
sys_uptime(void)
{
uint xticks;
-
+
acquire(&tickslock);
xticks = ticks;
release(&tickslock);
#include "types.h"
#include "defs.h"
#include "param.h"
-#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
#include "spinlock.h"
// Interrupt descriptor table (shared by all CPUs).
-struct gatedesc idt[256];
+static struct gatedesc idt[256];
extern uint vectors[]; // in vectors.S: array of 256 entry pointers
struct spinlock tickslock;
uint ticks;
for(i = 0; i < 256; i++)
SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0);
SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER);
-
+
initlock(&tickslock, "time");
}
cpu->id, tf->cs, tf->eip);
lapiceoi();
break;
-
+
//PAGEBREAK: 13
default:
if(proc == 0 || (tf->cs&3) == 0){
// In user space, assume process misbehaved.
cprintf("pid %d %s: trap %d err %d on cpu %d "
"eip 0x%x addr 0x%x--kill proc\n",
- proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip,
+ proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip,
rcr2());
proc->killed = 1;
}
// Force process exit if it has been killed and is in user space.
- // (If it is still executing in the kernel, let it keep running
+ // (If it is still executing in the kernel, let it keep running
// until it gets to the regular system call return.)
if(proc && proc->killed && (tf->cs&3) == DPL_USER)
exit();
pde = &pgdir[PDX(va)];
if(*pde & PTE_P){
- pgtab = (pte_t*)p2v(PTE_ADDR(*pde));
+ pgtab = (pte_t*)P2V(PTE_ADDR(*pde));
} else {
if(!alloc || (pgtab = (pte_t*)kalloc()) == 0)
return 0;
// The permissions here are overly generous, but they can
// be further restricted by the permissions in the page table
// entries, if necessary.
- *pde = v2p(pgtab) | PTE_P | PTE_W | PTE_U;
+ *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U;
}
return &pgtab[PTX(va)];
}
if((pgdir = (pde_t*)kalloc()) == 0)
return 0;
memset(pgdir, 0, PGSIZE);
- if (p2v(PHYSTOP) > (void*)DEVSPACE)
+ if (P2V(PHYSTOP) > (void*)DEVSPACE)
panic("PHYSTOP too high");
for(k = kmap; k < &kmap[NELEM(kmap)]; k++)
if(mappages(pgdir, k->virt, k->phys_end - k->phys_start,
void
switchkvm(void)
{
- lcr3(v2p(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.
ltr(SEG_TSS << 3);
if(p->pgdir == 0)
panic("switchuvm: no pgdir");
- lcr3(v2p(p->pgdir)); // switch to new address space
+ lcr3(V2P(p->pgdir)); // switch to new address space
popcli();
}
if ((mem = kalloc()) == 0)
panic("inituvm: cannot allocate memory");
memset(mem, 0, PGSIZE);
- if (mappages(pgdir, 0, PGSIZE, v2p(mem), PTE_W|PTE_U) < 0)
+ if (mappages(pgdir, 0, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0)
panic("inituvm: cannot create pagetable");
memmove(mem, init, sz);
}
n = sz - i;
else
n = PGSIZE;
- if(readi(ip, p2v(pa), offset+i, n) != n)
+ if(readi(ip, P2V(pa), offset+i, n) != n)
return -1;
}
return 0;
return 0;
}
memset(mem, 0, PGSIZE);
- if (mappages(pgdir, (char*)a, PGSIZE, v2p(mem), PTE_W|PTE_U) < 0)
+ if (mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0)
panic("allocuvm: cannot create pagetable");
}
return newsz;
pa = PTE_ADDR(*pte);
if(pa == 0)
panic("kfree");
- char *v = p2v(pa);
+ char *v = P2V(pa);
kfree(v);
*pte = 0;
}
deallocuvm(pgdir, KERNBASE, 0);
for(i = 0; i < NPDENTRIES; i++){
if(pgdir[i] & PTE_P){
- char * v = p2v(PTE_ADDR(pgdir[i]));
+ char * v = P2V(PTE_ADDR(pgdir[i]));
kfree(v);
}
}
flags = PTE_FLAGS(*pte);
if((mem = kalloc()) == 0)
goto bad;
- memmove(mem, (char*)p2v(pa), PGSIZE);
- if(mappages(d, (void*)i, PGSIZE, v2p(mem), flags) < 0)
+ memmove(mem, (char*)P2V(pa), PGSIZE);
+ if(mappages(d, (void*)i, PGSIZE, V2P(mem), flags) < 0)
goto bad;
}
return d;
return 0;
if((*pte & PTE_U) == 0)
return 0;
- return (char*)p2v(PTE_ADDR(*pte));
+ return (char*)P2V(PTE_ADDR(*pte));
}
// Copy len bytes from p to user address va in page table pgdir.