clang-format
This commit is contained in:
@@ -57,18 +57,14 @@
|
||||
|
||||
/* under dumbvm, always have 72k of user stack */
|
||||
/* (this must be > 64K so argument blocks of size ARG_MAX will fit) */
|
||||
#define DUMBVM_STACKPAGES 18
|
||||
#define DUMBVM_STACKPAGES 18
|
||||
|
||||
/*
|
||||
* Wrap ram_stealmem in a spinlock.
|
||||
*/
|
||||
static struct spinlock stealmem_lock = SPINLOCK_INITIALIZER;
|
||||
|
||||
void
|
||||
vm_bootstrap(void)
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
void vm_bootstrap(void) { /* Do nothing. */ }
|
||||
|
||||
/*
|
||||
* Check if we're in a context that can sleep. While most of the
|
||||
@@ -77,351 +73,311 @@ vm_bootstrap(void)
|
||||
* avoid the situation where syscall-layer code that works ok with
|
||||
* dumbvm starts blowing up during the VM assignment.
|
||||
*/
|
||||
static
|
||||
void
|
||||
dumbvm_can_sleep(void)
|
||||
{
|
||||
if (CURCPU_EXISTS()) {
|
||||
/* must not hold spinlocks */
|
||||
KASSERT(curcpu->c_spinlocks == 0);
|
||||
static void dumbvm_can_sleep(void) {
|
||||
if (CURCPU_EXISTS()) {
|
||||
/* must not hold spinlocks */
|
||||
KASSERT(curcpu->c_spinlocks == 0);
|
||||
|
||||
/* must not be in an interrupt handler */
|
||||
KASSERT(curthread->t_in_interrupt == 0);
|
||||
}
|
||||
/* must not be in an interrupt handler */
|
||||
KASSERT(curthread->t_in_interrupt == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
paddr_t
|
||||
getppages(unsigned long npages)
|
||||
{
|
||||
paddr_t addr;
|
||||
static paddr_t getppages(unsigned long npages) {
|
||||
paddr_t addr;
|
||||
|
||||
spinlock_acquire(&stealmem_lock);
|
||||
spinlock_acquire(&stealmem_lock);
|
||||
|
||||
addr = ram_stealmem(npages);
|
||||
addr = ram_stealmem(npages);
|
||||
|
||||
spinlock_release(&stealmem_lock);
|
||||
return addr;
|
||||
spinlock_release(&stealmem_lock);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Allocate/free some kernel-space virtual pages */
|
||||
vaddr_t
|
||||
alloc_kpages(unsigned npages)
|
||||
{
|
||||
paddr_t pa;
|
||||
vaddr_t alloc_kpages(unsigned npages) {
|
||||
paddr_t pa;
|
||||
|
||||
dumbvm_can_sleep();
|
||||
pa = getppages(npages);
|
||||
if (pa==0) {
|
||||
return 0;
|
||||
}
|
||||
return PADDR_TO_KVADDR(pa);
|
||||
dumbvm_can_sleep();
|
||||
pa = getppages(npages);
|
||||
if (pa == 0) {
|
||||
return 0;
|
||||
}
|
||||
return PADDR_TO_KVADDR(pa);
|
||||
}
|
||||
|
||||
void
|
||||
free_kpages(vaddr_t addr)
|
||||
{
|
||||
/* nothing - leak the memory. */
|
||||
void free_kpages(vaddr_t addr) {
|
||||
/* nothing - leak the memory. */
|
||||
|
||||
(void)addr;
|
||||
(void)addr;
|
||||
}
|
||||
|
||||
void
|
||||
vm_tlbshootdown(const struct tlbshootdown *ts)
|
||||
{
|
||||
(void)ts;
|
||||
panic("dumbvm tried to do tlb shootdown?!\n");
|
||||
void vm_tlbshootdown(const struct tlbshootdown *ts) {
|
||||
(void)ts;
|
||||
panic("dumbvm tried to do tlb shootdown?!\n");
|
||||
}
|
||||
|
||||
int
|
||||
vm_fault(int faulttype, vaddr_t faultaddress)
|
||||
{
|
||||
vaddr_t vbase1, vtop1, vbase2, vtop2, stackbase, stacktop;
|
||||
paddr_t paddr;
|
||||
int i;
|
||||
uint32_t ehi, elo;
|
||||
struct addrspace *as;
|
||||
int spl;
|
||||
int vm_fault(int faulttype, vaddr_t faultaddress) {
|
||||
vaddr_t vbase1, vtop1, vbase2, vtop2, stackbase, stacktop;
|
||||
paddr_t paddr;
|
||||
int i;
|
||||
uint32_t ehi, elo;
|
||||
struct addrspace *as;
|
||||
int spl;
|
||||
|
||||
faultaddress &= PAGE_FRAME;
|
||||
faultaddress &= PAGE_FRAME;
|
||||
|
||||
DEBUG(DB_VM, "dumbvm: fault: 0x%x\n", faultaddress);
|
||||
DEBUG(DB_VM, "dumbvm: fault: 0x%x\n", faultaddress);
|
||||
|
||||
switch (faulttype) {
|
||||
case VM_FAULT_READONLY:
|
||||
/* We always create pages read-write, so we can't get this */
|
||||
panic("dumbvm: got VM_FAULT_READONLY\n");
|
||||
case VM_FAULT_READ:
|
||||
case VM_FAULT_WRITE:
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
switch (faulttype) {
|
||||
case VM_FAULT_READONLY:
|
||||
/* We always create pages read-write, so we can't get this */
|
||||
panic("dumbvm: got VM_FAULT_READONLY\n");
|
||||
case VM_FAULT_READ:
|
||||
case VM_FAULT_WRITE:
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (curproc == NULL) {
|
||||
/*
|
||||
* No process. This is probably a kernel fault early
|
||||
* in boot. Return EFAULT so as to panic instead of
|
||||
* getting into an infinite faulting loop.
|
||||
*/
|
||||
return EFAULT;
|
||||
}
|
||||
if (curproc == NULL) {
|
||||
/*
|
||||
* No process. This is probably a kernel fault early
|
||||
* in boot. Return EFAULT so as to panic instead of
|
||||
* getting into an infinite faulting loop.
|
||||
*/
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
as = proc_getas();
|
||||
if (as == NULL) {
|
||||
/*
|
||||
* No address space set up. This is probably also a
|
||||
* kernel fault early in boot.
|
||||
*/
|
||||
return EFAULT;
|
||||
}
|
||||
as = proc_getas();
|
||||
if (as == NULL) {
|
||||
/*
|
||||
* No address space set up. This is probably also a
|
||||
* kernel fault early in boot.
|
||||
*/
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
/* Assert that the address space has been set up properly. */
|
||||
KASSERT(as->as_vbase1 != 0);
|
||||
KASSERT(as->as_pbase1 != 0);
|
||||
KASSERT(as->as_npages1 != 0);
|
||||
KASSERT(as->as_vbase2 != 0);
|
||||
KASSERT(as->as_pbase2 != 0);
|
||||
KASSERT(as->as_npages2 != 0);
|
||||
KASSERT(as->as_stackpbase != 0);
|
||||
KASSERT((as->as_vbase1 & PAGE_FRAME) == as->as_vbase1);
|
||||
KASSERT((as->as_pbase1 & PAGE_FRAME) == as->as_pbase1);
|
||||
KASSERT((as->as_vbase2 & PAGE_FRAME) == as->as_vbase2);
|
||||
KASSERT((as->as_pbase2 & PAGE_FRAME) == as->as_pbase2);
|
||||
KASSERT((as->as_stackpbase & PAGE_FRAME) == as->as_stackpbase);
|
||||
/* Assert that the address space has been set up properly. */
|
||||
KASSERT(as->as_vbase1 != 0);
|
||||
KASSERT(as->as_pbase1 != 0);
|
||||
KASSERT(as->as_npages1 != 0);
|
||||
KASSERT(as->as_vbase2 != 0);
|
||||
KASSERT(as->as_pbase2 != 0);
|
||||
KASSERT(as->as_npages2 != 0);
|
||||
KASSERT(as->as_stackpbase != 0);
|
||||
KASSERT((as->as_vbase1 & PAGE_FRAME) == as->as_vbase1);
|
||||
KASSERT((as->as_pbase1 & PAGE_FRAME) == as->as_pbase1);
|
||||
KASSERT((as->as_vbase2 & PAGE_FRAME) == as->as_vbase2);
|
||||
KASSERT((as->as_pbase2 & PAGE_FRAME) == as->as_pbase2);
|
||||
KASSERT((as->as_stackpbase & PAGE_FRAME) == as->as_stackpbase);
|
||||
|
||||
vbase1 = as->as_vbase1;
|
||||
vtop1 = vbase1 + as->as_npages1 * PAGE_SIZE;
|
||||
vbase2 = as->as_vbase2;
|
||||
vtop2 = vbase2 + as->as_npages2 * PAGE_SIZE;
|
||||
stackbase = USERSTACK - DUMBVM_STACKPAGES * PAGE_SIZE;
|
||||
stacktop = USERSTACK;
|
||||
vbase1 = as->as_vbase1;
|
||||
vtop1 = vbase1 + as->as_npages1 * PAGE_SIZE;
|
||||
vbase2 = as->as_vbase2;
|
||||
vtop2 = vbase2 + as->as_npages2 * PAGE_SIZE;
|
||||
stackbase = USERSTACK - DUMBVM_STACKPAGES * PAGE_SIZE;
|
||||
stacktop = USERSTACK;
|
||||
|
||||
if (faultaddress >= vbase1 && faultaddress < vtop1) {
|
||||
paddr = (faultaddress - vbase1) + as->as_pbase1;
|
||||
}
|
||||
else if (faultaddress >= vbase2 && faultaddress < vtop2) {
|
||||
paddr = (faultaddress - vbase2) + as->as_pbase2;
|
||||
}
|
||||
else if (faultaddress >= stackbase && faultaddress < stacktop) {
|
||||
paddr = (faultaddress - stackbase) + as->as_stackpbase;
|
||||
}
|
||||
else {
|
||||
return EFAULT;
|
||||
}
|
||||
if (faultaddress >= vbase1 && faultaddress < vtop1) {
|
||||
paddr = (faultaddress - vbase1) + as->as_pbase1;
|
||||
} else if (faultaddress >= vbase2 && faultaddress < vtop2) {
|
||||
paddr = (faultaddress - vbase2) + as->as_pbase2;
|
||||
} else if (faultaddress >= stackbase && faultaddress < stacktop) {
|
||||
paddr = (faultaddress - stackbase) + as->as_stackpbase;
|
||||
} else {
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
/* make sure it's page-aligned */
|
||||
KASSERT((paddr & PAGE_FRAME) == paddr);
|
||||
/* make sure it's page-aligned */
|
||||
KASSERT((paddr & PAGE_FRAME) == paddr);
|
||||
|
||||
/* Disable interrupts on this CPU while frobbing the TLB. */
|
||||
spl = splhigh();
|
||||
/* Disable interrupts on this CPU while frobbing the TLB. */
|
||||
spl = splhigh();
|
||||
|
||||
for (i=0; i<NUM_TLB; i++) {
|
||||
tlb_read(&ehi, &elo, i);
|
||||
if (elo & TLBLO_VALID) {
|
||||
continue;
|
||||
}
|
||||
ehi = faultaddress;
|
||||
elo = paddr | TLBLO_DIRTY | TLBLO_VALID;
|
||||
DEBUG(DB_VM, "dumbvm: 0x%x -> 0x%x\n", faultaddress, paddr);
|
||||
tlb_write(ehi, elo, i);
|
||||
splx(spl);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < NUM_TLB; i++) {
|
||||
tlb_read(&ehi, &elo, i);
|
||||
if (elo & TLBLO_VALID) {
|
||||
continue;
|
||||
}
|
||||
ehi = faultaddress;
|
||||
elo = paddr | TLBLO_DIRTY | TLBLO_VALID;
|
||||
DEBUG(DB_VM, "dumbvm: 0x%x -> 0x%x\n", faultaddress, paddr);
|
||||
tlb_write(ehi, elo, i);
|
||||
splx(spl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kprintf("dumbvm: Ran out of TLB entries - cannot handle page fault\n");
|
||||
splx(spl);
|
||||
return EFAULT;
|
||||
kprintf("dumbvm: Ran out of TLB entries - cannot handle page fault\n");
|
||||
splx(spl);
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
struct addrspace *
|
||||
as_create(void)
|
||||
{
|
||||
struct addrspace *as = kmalloc(sizeof(struct addrspace));
|
||||
if (as==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
struct addrspace *as_create(void) {
|
||||
struct addrspace *as = kmalloc(sizeof(struct addrspace));
|
||||
if (as == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
as->as_vbase1 = 0;
|
||||
as->as_pbase1 = 0;
|
||||
as->as_npages1 = 0;
|
||||
as->as_vbase2 = 0;
|
||||
as->as_pbase2 = 0;
|
||||
as->as_npages2 = 0;
|
||||
as->as_stackpbase = 0;
|
||||
as->as_vbase1 = 0;
|
||||
as->as_pbase1 = 0;
|
||||
as->as_npages1 = 0;
|
||||
as->as_vbase2 = 0;
|
||||
as->as_pbase2 = 0;
|
||||
as->as_npages2 = 0;
|
||||
as->as_stackpbase = 0;
|
||||
|
||||
return as;
|
||||
return as;
|
||||
}
|
||||
|
||||
void
|
||||
as_destroy(struct addrspace *as)
|
||||
{
|
||||
dumbvm_can_sleep();
|
||||
kfree(as);
|
||||
void as_destroy(struct addrspace *as) {
|
||||
dumbvm_can_sleep();
|
||||
kfree(as);
|
||||
}
|
||||
|
||||
void
|
||||
as_activate(void)
|
||||
{
|
||||
int i, spl;
|
||||
struct addrspace *as;
|
||||
void as_activate(void) {
|
||||
int i, spl;
|
||||
struct addrspace *as;
|
||||
|
||||
as = proc_getas();
|
||||
if (as == NULL) {
|
||||
return;
|
||||
}
|
||||
as = proc_getas();
|
||||
if (as == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable interrupts on this CPU while frobbing the TLB. */
|
||||
spl = splhigh();
|
||||
/* Disable interrupts on this CPU while frobbing the TLB. */
|
||||
spl = splhigh();
|
||||
|
||||
for (i=0; i<NUM_TLB; i++) {
|
||||
tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
|
||||
}
|
||||
for (i = 0; i < NUM_TLB; i++) {
|
||||
tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
|
||||
}
|
||||
|
||||
splx(spl);
|
||||
splx(spl);
|
||||
}
|
||||
|
||||
void
|
||||
as_deactivate(void)
|
||||
{
|
||||
/* nothing */
|
||||
void as_deactivate(void) { /* nothing */ }
|
||||
|
||||
int as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
|
||||
int readable, int writeable, int executable) {
|
||||
size_t npages;
|
||||
|
||||
dumbvm_can_sleep();
|
||||
|
||||
/* Align the region. First, the base... */
|
||||
sz += vaddr & ~(vaddr_t)PAGE_FRAME;
|
||||
vaddr &= PAGE_FRAME;
|
||||
|
||||
/* ...and now the length. */
|
||||
sz = (sz + PAGE_SIZE - 1) & PAGE_FRAME;
|
||||
|
||||
npages = sz / PAGE_SIZE;
|
||||
|
||||
/* We don't use these - all pages are read-write */
|
||||
(void)readable;
|
||||
(void)writeable;
|
||||
(void)executable;
|
||||
|
||||
if (as->as_vbase1 == 0) {
|
||||
as->as_vbase1 = vaddr;
|
||||
as->as_npages1 = npages;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (as->as_vbase2 == 0) {
|
||||
as->as_vbase2 = vaddr;
|
||||
as->as_npages2 = npages;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Support for more than two regions is not available.
|
||||
*/
|
||||
kprintf("dumbvm: Warning: too many regions\n");
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int
|
||||
as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
|
||||
int readable, int writeable, int executable)
|
||||
{
|
||||
size_t npages;
|
||||
|
||||
dumbvm_can_sleep();
|
||||
|
||||
/* Align the region. First, the base... */
|
||||
sz += vaddr & ~(vaddr_t)PAGE_FRAME;
|
||||
vaddr &= PAGE_FRAME;
|
||||
|
||||
/* ...and now the length. */
|
||||
sz = (sz + PAGE_SIZE - 1) & PAGE_FRAME;
|
||||
|
||||
npages = sz / PAGE_SIZE;
|
||||
|
||||
/* We don't use these - all pages are read-write */
|
||||
(void)readable;
|
||||
(void)writeable;
|
||||
(void)executable;
|
||||
|
||||
if (as->as_vbase1 == 0) {
|
||||
as->as_vbase1 = vaddr;
|
||||
as->as_npages1 = npages;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (as->as_vbase2 == 0) {
|
||||
as->as_vbase2 = vaddr;
|
||||
as->as_npages2 = npages;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Support for more than two regions is not available.
|
||||
*/
|
||||
kprintf("dumbvm: Warning: too many regions\n");
|
||||
return ENOSYS;
|
||||
static void as_zero_region(paddr_t paddr, unsigned npages) {
|
||||
bzero((void *)PADDR_TO_KVADDR(paddr), npages * PAGE_SIZE);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
as_zero_region(paddr_t paddr, unsigned npages)
|
||||
{
|
||||
bzero((void *)PADDR_TO_KVADDR(paddr), npages * PAGE_SIZE);
|
||||
int as_prepare_load(struct addrspace *as) {
|
||||
KASSERT(as->as_pbase1 == 0);
|
||||
KASSERT(as->as_pbase2 == 0);
|
||||
KASSERT(as->as_stackpbase == 0);
|
||||
|
||||
dumbvm_can_sleep();
|
||||
|
||||
as->as_pbase1 = getppages(as->as_npages1);
|
||||
if (as->as_pbase1 == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as->as_pbase2 = getppages(as->as_npages2);
|
||||
if (as->as_pbase2 == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as->as_stackpbase = getppages(DUMBVM_STACKPAGES);
|
||||
if (as->as_stackpbase == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as_zero_region(as->as_pbase1, as->as_npages1);
|
||||
as_zero_region(as->as_pbase2, as->as_npages2);
|
||||
as_zero_region(as->as_stackpbase, DUMBVM_STACKPAGES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
as_prepare_load(struct addrspace *as)
|
||||
{
|
||||
KASSERT(as->as_pbase1 == 0);
|
||||
KASSERT(as->as_pbase2 == 0);
|
||||
KASSERT(as->as_stackpbase == 0);
|
||||
|
||||
dumbvm_can_sleep();
|
||||
|
||||
as->as_pbase1 = getppages(as->as_npages1);
|
||||
if (as->as_pbase1 == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as->as_pbase2 = getppages(as->as_npages2);
|
||||
if (as->as_pbase2 == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as->as_stackpbase = getppages(DUMBVM_STACKPAGES);
|
||||
if (as->as_stackpbase == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as_zero_region(as->as_pbase1, as->as_npages1);
|
||||
as_zero_region(as->as_pbase2, as->as_npages2);
|
||||
as_zero_region(as->as_stackpbase, DUMBVM_STACKPAGES);
|
||||
|
||||
return 0;
|
||||
int as_complete_load(struct addrspace *as) {
|
||||
dumbvm_can_sleep();
|
||||
(void)as;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
as_complete_load(struct addrspace *as)
|
||||
{
|
||||
dumbvm_can_sleep();
|
||||
(void)as;
|
||||
return 0;
|
||||
int as_define_stack(struct addrspace *as, vaddr_t *stackptr) {
|
||||
KASSERT(as->as_stackpbase != 0);
|
||||
|
||||
*stackptr = USERSTACK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
as_define_stack(struct addrspace *as, vaddr_t *stackptr)
|
||||
{
|
||||
KASSERT(as->as_stackpbase != 0);
|
||||
int as_copy(struct addrspace *old, struct addrspace **ret) {
|
||||
struct addrspace *new;
|
||||
|
||||
*stackptr = USERSTACK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
as_copy(struct addrspace *old, struct addrspace **ret)
|
||||
{
|
||||
struct addrspace *new;
|
||||
|
||||
dumbvm_can_sleep();
|
||||
|
||||
new = as_create();
|
||||
if (new==NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
new->as_vbase1 = old->as_vbase1;
|
||||
new->as_npages1 = old->as_npages1;
|
||||
new->as_vbase2 = old->as_vbase2;
|
||||
new->as_npages2 = old->as_npages2;
|
||||
|
||||
/* (Mis)use as_prepare_load to allocate some physical memory. */
|
||||
if (as_prepare_load(new)) {
|
||||
as_destroy(new);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
KASSERT(new->as_pbase1 != 0);
|
||||
KASSERT(new->as_pbase2 != 0);
|
||||
KASSERT(new->as_stackpbase != 0);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_pbase1),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_pbase1),
|
||||
old->as_npages1*PAGE_SIZE);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_pbase2),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_pbase2),
|
||||
old->as_npages2*PAGE_SIZE);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_stackpbase),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_stackpbase),
|
||||
DUMBVM_STACKPAGES*PAGE_SIZE);
|
||||
|
||||
*ret = new;
|
||||
return 0;
|
||||
dumbvm_can_sleep();
|
||||
|
||||
new = as_create();
|
||||
if (new == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
new->as_vbase1 = old->as_vbase1;
|
||||
new->as_npages1 = old->as_npages1;
|
||||
new->as_vbase2 = old->as_vbase2;
|
||||
new->as_npages2 = old->as_npages2;
|
||||
|
||||
/* (Mis)use as_prepare_load to allocate some physical memory. */
|
||||
if (as_prepare_load(new)) {
|
||||
as_destroy(new);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
KASSERT(new->as_pbase1 != 0);
|
||||
KASSERT(new->as_pbase2 != 0);
|
||||
KASSERT(new->as_stackpbase != 0);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_pbase1),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_pbase1),
|
||||
old->as_npages1 * PAGE_SIZE);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_pbase2),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_pbase2),
|
||||
old->as_npages2 * PAGE_SIZE);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_stackpbase),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_stackpbase),
|
||||
DUMBVM_STACKPAGES * PAGE_SIZE);
|
||||
|
||||
*ret = new;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,45 +32,41 @@
|
||||
#include <vm.h>
|
||||
#include <mainbus.h>
|
||||
|
||||
vaddr_t firstfree; /* first free virtual address; set by start.S */
|
||||
|
||||
vaddr_t firstfree; /* first free virtual address; set by start.S */
|
||||
|
||||
static paddr_t firstpaddr; /* address of first free physical page */
|
||||
static paddr_t lastpaddr; /* one past end of last free physical page */
|
||||
static paddr_t firstpaddr; /* address of first free physical page */
|
||||
static paddr_t lastpaddr; /* one past end of last free physical page */
|
||||
|
||||
/*
|
||||
* Called very early in system boot to figure out how much physical
|
||||
* RAM is available.
|
||||
*/
|
||||
void
|
||||
ram_bootstrap(void)
|
||||
{
|
||||
size_t ramsize;
|
||||
void ram_bootstrap(void) {
|
||||
size_t ramsize;
|
||||
|
||||
/* Get size of RAM. */
|
||||
ramsize = mainbus_ramsize();
|
||||
/* Get size of RAM. */
|
||||
ramsize = mainbus_ramsize();
|
||||
|
||||
/*
|
||||
* This is the same as the last physical address, as long as
|
||||
* we have less than 512 megabytes of memory. If we had more,
|
||||
* we wouldn't be able to access it all through kseg0 and
|
||||
* everything would get a lot more complicated. This is not a
|
||||
* case we are going to worry about.
|
||||
*/
|
||||
if (ramsize > 512*1024*1024) {
|
||||
ramsize = 512*1024*1024;
|
||||
}
|
||||
/*
|
||||
* This is the same as the last physical address, as long as
|
||||
* we have less than 512 megabytes of memory. If we had more,
|
||||
* we wouldn't be able to access it all through kseg0 and
|
||||
* everything would get a lot more complicated. This is not a
|
||||
* case we are going to worry about.
|
||||
*/
|
||||
if (ramsize > 512 * 1024 * 1024) {
|
||||
ramsize = 512 * 1024 * 1024;
|
||||
}
|
||||
|
||||
lastpaddr = ramsize;
|
||||
lastpaddr = ramsize;
|
||||
|
||||
/*
|
||||
* Get first free virtual address from where start.S saved it.
|
||||
* Convert to physical address.
|
||||
*/
|
||||
firstpaddr = firstfree - MIPS_KSEG0;
|
||||
/*
|
||||
* Get first free virtual address from where start.S saved it.
|
||||
* Convert to physical address.
|
||||
*/
|
||||
firstpaddr = firstfree - MIPS_KSEG0;
|
||||
|
||||
kprintf("%uk physical memory available\n",
|
||||
(lastpaddr-firstpaddr)/1024);
|
||||
kprintf("%uk physical memory available\n", (lastpaddr - firstpaddr) / 1024);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -91,22 +87,20 @@ ram_bootstrap(void)
|
||||
* This function should not be called once the VM system is initialized,
|
||||
* so it is not synchronized.
|
||||
*/
|
||||
paddr_t
|
||||
ram_stealmem(unsigned long npages)
|
||||
{
|
||||
size_t size;
|
||||
paddr_t paddr;
|
||||
paddr_t ram_stealmem(unsigned long npages) {
|
||||
size_t size;
|
||||
paddr_t paddr;
|
||||
|
||||
size = npages * PAGE_SIZE;
|
||||
size = npages * PAGE_SIZE;
|
||||
|
||||
if (firstpaddr + size > lastpaddr) {
|
||||
return 0;
|
||||
}
|
||||
if (firstpaddr + size > lastpaddr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
paddr = firstpaddr;
|
||||
firstpaddr += size;
|
||||
paddr = firstpaddr;
|
||||
firstpaddr += size;
|
||||
|
||||
return paddr;
|
||||
return paddr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -124,11 +118,7 @@ ram_stealmem(unsigned long npages)
|
||||
* initialize the VM system, after which the VM system should take
|
||||
* charge of knowing what memory exists.
|
||||
*/
|
||||
paddr_t
|
||||
ram_getsize(void)
|
||||
{
|
||||
return lastpaddr;
|
||||
}
|
||||
paddr_t ram_getsize(void) { return lastpaddr; }
|
||||
|
||||
/*
|
||||
* This function is intended to be called by the VM system when it
|
||||
@@ -142,12 +132,10 @@ ram_getsize(void)
|
||||
* This function should not be called once the VM system is initialized,
|
||||
* so it is not synchronized.
|
||||
*/
|
||||
paddr_t
|
||||
ram_getfirstfree(void)
|
||||
{
|
||||
paddr_t ret;
|
||||
paddr_t ram_getfirstfree(void) {
|
||||
paddr_t ret;
|
||||
|
||||
ret = firstpaddr;
|
||||
firstpaddr = lastpaddr = 0;
|
||||
return ret;
|
||||
ret = firstpaddr;
|
||||
firstpaddr = lastpaddr = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user