Complete rework of the PowerPC pmap and a number of other bits in the early

boot sequence.

The new pmap.c is based on NetBSD's newer pmap.c (for the mpc6xx processors)
which is 70% faster than the older code that the original pmap.c was based
on.  It has also been based on the framework established by jake's initial
sparc64 pmap.c.

There is no change to how far the kernel gets (it makes it to the mountroot
prompt in psim) but the new pmap code is a lot cleaner.

Obtained from:	NetBSD (pmap code)
This commit is contained in:
Benno Rice 2002-02-14 01:39:11 +00:00
parent cfd8a00918
commit 5244eac968
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=90643
23 changed files with 5926 additions and 5242 deletions

View File

@ -64,7 +64,7 @@
#include <machine/trap.h>
#include <machine/param.h>
#include <machine/pmap.h>
#include <machine/sr.h>
#include <machine/psl.h>
#include <machine/asm.h>
@ -984,7 +984,7 @@ s_dsitrap:
mfctr 31 /* & CTR */
mfdar 3
s_pte_spill:
bl pte_spill /* try a spill */
bl pmap_pte_spill /* try a spill */
or. 3,3,3
mtctr 31 /* restore CTR */
mtlr 30 /* and trap type */
@ -1071,8 +1071,8 @@ s_isitrap:
stw 4,12(1); \
stw 3,8(1); \
/* interrupts are recoverable here, and enable translation */ \
lis 3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h; \
ori 3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l; \
lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \
ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \
mtsr KERNEL_SR,3; \
mfmsr 5; \
ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \

View File

@ -116,8 +116,12 @@ int cold = 1;
struct mtx sched_lock;
struct mtx Giant;
struct user *proc0uarea;
vm_offset_t proc0kstack;
char pcpu0[PAGE_SIZE];
char uarea0[UAREA_PAGES * PAGE_SIZE];
struct trapframe frame0;
vm_offset_t kstack0;
vm_offset_t kstack0_phys;
char machine[] = "powerpc";
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
@ -156,17 +160,11 @@ sysctl_hw_physmem(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD,
0, 0, sysctl_hw_physmem, "IU", "");
struct msgbuf *msgbufp = 0;
int Maxmem = 0;
long dumplo;
vm_offset_t phys_avail[10];
static int chosen;
static struct trapframe proc0_tf;
struct pmap ofw_pmap;
extern int ofmsr;
@ -262,6 +260,9 @@ identifycpu()
version = pvr >> 16;
revision = pvr & 0xffff;
switch (version) {
case 0x0000:
sprintf(model, "Simulator (psim)");
break;
case 0x0001:
sprintf(model, "601");
break;
@ -346,6 +347,77 @@ extern ddblow, ddbsize;
extern ipkdblow, ipkdbsize;
#endif
void
powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
{
struct pcpu *pc;
vm_offset_t off;
/*
* Initialize the console before printing anything.
*/
cninit();
/*
* Initialize tunables.
*/
init_param1();
init_param2(physmem);
/*
* Initialise virtual memory.
*/
ofmsr |= PSL_IR | PSL_DR;
pmap_bootstrap(startkernel, endkernel);
/*
* XXX: Initialize the interrupt tables.
*/
bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
/*
* Initialize proc0.
*/
proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0);
/* proc0.p_md.md_utrap = NULL; */
proc0.p_uarea = (struct user *)uarea0;
proc0.p_stats = &proc0.p_uarea->u_stats;
thread0.td_kstack = kstack0;
thread0.td_pcb = (struct pcb *)
(thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
/* frame0.tf_tstate = TSTATE_IE | TSTATE_PEF; */
thread0.td_frame = &frame0;
LIST_INIT(&thread0.td_contested);
/*
* Set up per-cpu data.
*/
pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1;
pcpu_init(pc, 0, sizeof(struct pcpu));
pc->pc_curthread = &thread0;
pc->pc_curpcb = thread0.td_pcb;
/* pc->pc_mid = mid; */
__asm __volatile("mtsprg 0, %0" :: "r"(pc));
/*
* Map and initialise the message buffer.
*/
for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
msgbufinit(msgbufp, MSGBUF_SIZE);
/*
* Initialize mutexes.
*/
mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE);
mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE);
mtx_init(&proc0.p_mtx, "process lock", MTX_DEF);
mtx_lock(&Giant);
}
#if 0 /* XXX: Old powerpc_init */
void
powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
{
@ -598,6 +670,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
thread0.td_frame = &proc0_tf;
}
#endif
static int N_mapping;
static struct {
@ -916,8 +989,7 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
}
void
enable_fpu(pcb)
struct pcb *pcb;
enable_fpu(struct pcb *pcb)
{
int msr, scratch;
@ -964,8 +1036,7 @@ enable_fpu(pcb)
}
void
save_fpu(pcb)
struct pcb *pcb;
save_fpu(struct pcb *pcb)
{
int msr, scratch;

File diff suppressed because it is too large Load Diff

View File

@ -48,12 +48,18 @@ static const char rcsid[] =
#include <dev/ofw/openfirm.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <machine/powerpc.h>
#define OFMEM_REGIONS 32
static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
extern long ofmsr;
extern struct pmap ofw_pmap;
extern int pmap_bootstrapped;
static int (*ofwcall)(void *);
/*
@ -95,8 +101,48 @@ openfirmware(void *args)
{
long oldmsr;
int result;
u_int srsave[16];
__asm( "\t"
if (pmap_bootstrapped) {
__asm __volatile("mfsr %0,0" : "=r"(srsave[0]));
__asm __volatile("mfsr %0,1" : "=r"(srsave[1]));
__asm __volatile("mfsr %0,2" : "=r"(srsave[2]));
__asm __volatile("mfsr %0,3" : "=r"(srsave[3]));
__asm __volatile("mfsr %0,4" : "=r"(srsave[4]));
__asm __volatile("mfsr %0,5" : "=r"(srsave[5]));
__asm __volatile("mfsr %0,6" : "=r"(srsave[6]));
__asm __volatile("mfsr %0,7" : "=r"(srsave[7]));
__asm __volatile("mfsr %0,8" : "=r"(srsave[8]));
__asm __volatile("mfsr %0,9" : "=r"(srsave[9]));
__asm __volatile("mfsr %0,10" : "=r"(srsave[10]));
__asm __volatile("mfsr %0,11" : "=r"(srsave[11]));
__asm __volatile("mfsr %0,12" : "=r"(srsave[12]));
__asm __volatile("mfsr %0,13" : "=r"(srsave[13]));
__asm __volatile("mfsr %0,14" : "=r"(srsave[14]));
__asm __volatile("mfsr %0,15" : "=r"(srsave[15]));
__asm __volatile("mtsr 0,%0" :: "r"(ofw_pmap.pm_sr[0]));
__asm __volatile("mtsr 1,%0" :: "r"(ofw_pmap.pm_sr[1]));
__asm __volatile("mtsr 2,%0" :: "r"(ofw_pmap.pm_sr[2]));
__asm __volatile("mtsr 3,%0" :: "r"(ofw_pmap.pm_sr[3]));
__asm __volatile("mtsr 4,%0" :: "r"(ofw_pmap.pm_sr[4]));
__asm __volatile("mtsr 5,%0" :: "r"(ofw_pmap.pm_sr[5]));
__asm __volatile("mtsr 6,%0" :: "r"(ofw_pmap.pm_sr[6]));
__asm __volatile("mtsr 7,%0" :: "r"(ofw_pmap.pm_sr[7]));
__asm __volatile("mtsr 8,%0" :: "r"(ofw_pmap.pm_sr[8]));
__asm __volatile("mtsr 9,%0" :: "r"(ofw_pmap.pm_sr[9]));
__asm __volatile("mtsr 10,%0" :: "r"(ofw_pmap.pm_sr[10]));
__asm __volatile("mtsr 11,%0" :: "r"(ofw_pmap.pm_sr[11]));
__asm __volatile("mtsr 12,%0" :: "r"(ofw_pmap.pm_sr[12]));
__asm __volatile("mtsr 13,%0" :: "r"(ofw_pmap.pm_sr[13]));
__asm __volatile("mtsr 14,%0" :: "r"(ofw_pmap.pm_sr[14]));
__asm __volatile("mtsr 15,%0" :: "r"(ofw_pmap.pm_sr[15]));
}
ofmsr |= PSL_RI|PSL_EE;
__asm __volatile( "\t"
"sync\n\t"
"mfmsr %0\n\t"
"mtmsr %1\n\t"
"isync\n"
@ -112,6 +158,27 @@ openfirmware(void *args)
: : "r" (oldmsr)
);
if (pmap_bootstrapped) {
__asm __volatile("mtsr 0,%0" :: "r"(srsave[0]));
__asm __volatile("mtsr 1,%0" :: "r"(srsave[1]));
__asm __volatile("mtsr 2,%0" :: "r"(srsave[2]));
__asm __volatile("mtsr 3,%0" :: "r"(srsave[3]));
__asm __volatile("mtsr 4,%0" :: "r"(srsave[4]));
__asm __volatile("mtsr 5,%0" :: "r"(srsave[5]));
__asm __volatile("mtsr 6,%0" :: "r"(srsave[6]));
__asm __volatile("mtsr 7,%0" :: "r"(srsave[7]));
__asm __volatile("mtsr 8,%0" :: "r"(srsave[8]));
__asm __volatile("mtsr 9,%0" :: "r"(srsave[9]));
__asm __volatile("mtsr 10,%0" :: "r"(srsave[10]));
__asm __volatile("mtsr 11,%0" :: "r"(srsave[11]));
__asm __volatile("mtsr 12,%0" :: "r"(srsave[12]));
__asm __volatile("mtsr 13,%0" :: "r"(srsave[13]));
__asm __volatile("mtsr 14,%0" :: "r"(srsave[14]));
__asm __volatile("mtsr 15,%0" :: "r"(srsave[15]));
__asm __volatile("sync");
}
return (result);
}

View File

@ -62,7 +62,7 @@
#include <machine/trap.h>
#include <machine/param.h>
#include <machine/pmap.h>
#include <machine/sr.h>
#include <machine/psl.h>
#include <machine/asm.h>

View File

@ -467,7 +467,7 @@ trap_pfault(struct trapframe *frame, int user)
return (SIGSEGV);
map = kernel_map;
} else {
sr_t user_sr;
u_int user_sr;
if (p->p_vmspace == NULL)
return (SIGSEGV);

View File

@ -126,9 +126,10 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
struct trapframe *tf;
struct callframe *cf;
struct switchframe *sf;
caddr_t stktop1, stktop2;
struct pcb *pcb2;
struct pcb *pcb;
KASSERT(td1 == curthread || td1 == thread0,
("cpu_fork: p1 not curproc and not proc0"));
CTR3(KTR_PROC, "cpu_fork: called td1=%08x p2=%08x flags=%x", (u_int)td1, (u_int)p2, flags);
if ((flags & RFPROC) == 0)
@ -136,39 +137,42 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
p1 = td1->td_proc;
/* Point the pcb to the top of the stack */
pcb2 = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
td2->td_pcb = pcb2;
pcb = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
sizeof(struct pcb));
td2->td_pcb = pcb;
/* Copy p1's pcb. */
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
/* Copy the pcb */
bcopy(td1->td_pcb, pcb, sizeof(struct pcb));
/*
* Create a new fresh stack for the new process.
* Create a fresh stack for the new process.
* Copy the trap frame for the return to user mode as if from a
* syscall. This copies most of the user mode register values.
*/
td2->td_frame = (struct trapframe *)td2->td_pcb - 1;
bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe));
stktop2 = (caddr_t)td2->td_frame;
tf = (struct trapframe *)pcb - 1;
bcopy(td1->td_frame, tf, sizeof(*tf));
cf = (struct callframe *)stktop2;
/* XXX: Set up trap frame? */
td2->td_frame = tf;
/*
* There happens to be a callframe, too.
*/
cf = (struct callframe *)tf - 1;
cf->lr = (int)fork_trampoline;
stktop2 -= 16;
cf = (struct callframe *)stktop2;
cf->r31 = (register_t)fork_return;
cf->r30 = (register_t)td2;
stktop2 -= roundup(sizeof *sf, 16);
sf = (struct switchframe *)stktop2;
bzero((void *)sf, sizeof *sf);
/*
* Below that, we allocate the switch frame.
*/
sf = (struct switchframe *)cf - 1;
sf->sp = (int)cf;
sf->user_sr = kernel_pmap->pm_sr[USER_SR];
pcb2->pcb_sp = (int)stktop2;
pcb2->pcb_spl = 0;
pcb->pcb_sp = (int)sf;
/*
* Now cpu_switch() can schedule the new process.
*/
}
/*
@ -233,10 +237,10 @@ cpu_coredump(td, vp, cred)
struct vnode *vp;
struct ucred *cred;
{
struct proc *p = td->td_proc;
return (vn_rdwr(UIO_WRITE, vp, (caddr_t)p->p_uarea, ctob(UAREA_PAGES),
(off_t)0, UIO_SYSSPACE, IO_UNIT, cred, (int *)NULL, p));
return (vn_rdwr(UIO_WRITE, vp, (caddr_t)td->td_proc->p_uarea,
ctob(UAREA_PAGES), (off_t)0, UIO_SYSSPACE, IO_UNIT, cred,
(int *)NULL, td));
}
/*

View File

@ -39,6 +39,9 @@ extern int szsigcode;
extern int Maxmem;
extern int busdma_swi_pending;
extern vm_offset_t kstack0;
extern vm_offset_t kstack0_phys;
struct fpreg;
struct proc;
struct reg;

View File

@ -42,6 +42,8 @@
* Machine dependent constants for PowerPC (32-bit only currently)
*/
#include <machine/pte.h>
/*
* Round p (pointer or byte index) up to a correctly-aligned value
* for all data types (int, long, ...). The result is unsigned int
@ -113,7 +115,8 @@
#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
#ifndef KSTACK_UPAGES
#define KSTACK_PAGES 2 /* includes pcb */
#define KSTACK_PAGES 2 /* includes pcb */
#define KSTACK_GUARD_PAGES 1
#endif
#define USPACE (KSTACK_PAGES * PAGE_SIZE) /* total size of pcb */
#define UAREA_PAGES 1 /* holds struct user WITHOUT PCB */
@ -179,6 +182,7 @@
/* XXX: NetBSD defines that we're using for the moment */
#define USER_SR 13
#define KERNEL_SR 14
#define KERNEL_VSIDBITS 0xfffff
#define KERNEL_SEGMENT (0xfffff0 + KERNEL_SR)
#define EMPTY_SEGMENT 0xfffff0
#define USER_ADDR ((void *)(USER_SR << ADDR_SR_SHFT))

View File

@ -35,102 +35,52 @@
#ifndef _MACHINE_PMAP_H_
#define _MACHINE_PMAP_H_
#include <machine/pte.h>
#include <machine/sr.h>
/*
* Segment registers
*/
#ifndef LOCORE
typedef u_int sr_t;
#endif /* LOCORE */
#define SR_TYPE 0x80000000
#define SR_SUKEY 0x40000000
#define SR_PRKEY 0x20000000
#define SR_VSID 0x00ffffff
#ifndef LOCORE
struct pv_entry {
struct pv_entry *pv_next; /* Linked list of mappings */
int pv_idx; /* Index into ptable */
vm_offset_t pv_va; /* virtual address of mapping */
};
struct md_page {
int pv_list_count;
int pv_flags;
TAILQ_HEAD(,pv_entry) pv_list;
};
/*
* Pmap stuff
*/
struct pmap {
sr_t pm_sr[16]; /* segments used in this pmap */
int pm_refs; /* ref count */
struct pmap_statistics pm_stats; /* pmap statistics */
struct pmap {
u_int pm_sr[16];
u_int pm_active;
u_int pm_context;
u_int pm_count;
struct pmap_statistics pm_stats;
};
typedef struct pmap *pmap_t;
typedef struct pv_entry *pv_entry_t;
struct pvo_entry {
LIST_ENTRY(pvo_entry) pvo_vlink; /* Link to common virt page */
LIST_ENTRY(pvo_entry) pvo_olink; /* Link to overflow entry */
struct pte pvo_pte; /* PTE */
pmap_t pvo_pmap; /* Owning pmap */
vm_offset_t pvo_vaddr; /* VA of entry */
};
LIST_HEAD(pvo_head, pvo_entry);
#ifdef _KERNEL
struct md_page {
u_int mdpg_attrs;
struct pvo_head mdpg_pvoh;
};
#define pmap_clear_modify(pg) (ptemodify((pg), PTE_CHG, 0))
#define pmap_clear_reference(pg) (ptemodify((pg), PTE_REF, 0))
#define pmap_is_modified(pg) (ptebits((pg), PTE_CHG))
#define pmap_is_referenced(pg) (ptebits((pg), PTE_REF))
#define pmap_unwire(pm, va)
extern struct pmap kernel_pmap_store;
#define kernel_pmap (&kernel_pmap_store)
#define pmap_phys_address(x) (x)
#define pmap_resident_count(pm) (pm->pm_stats.resident_count)
#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
#ifdef _KERNEL
extern pmap_t kernel_pmap;
void pmap_bootstrap(vm_offset_t, vm_offset_t);
vm_offset_t pmap_kextract(vm_offset_t);
extern vm_offset_t avail_end;
extern vm_offset_t avail_start;
extern vm_offset_t phys_avail[];
extern vm_offset_t virtual_avail;
extern vm_offset_t virtual_end;
int pmap_pte_spill(vm_offset_t);
void pmap_bootstrap __P((void));
void *pmap_mapdev __P((vm_offset_t, vm_size_t));
void pmap_setavailmem __P((u_int kernelstart, u_int kernelend));
vm_offset_t pmap_steal_memory __P((vm_size_t));
boolean_t ptemodify __P((struct vm_page *, u_int, u_int));
int ptebits __P((struct vm_page *, int));
extern vm_offset_t avail_start;
extern vm_offset_t avail_end;
extern vm_offset_t phys_avail[];
extern vm_offset_t virtual_avail;
extern vm_offset_t virtual_end;
extern vm_offset_t msgbuf_phys;
#if 0
#define PMAP_NEED_PROCWR
void pmap_procwr __P((struct proc *, vaddr_t, size_t));
#endif
/*
* Alternate mapping hooks for pool pages. Avoids thrashing the TLB.
*
* Note: This won't work if we have more memory than can be direct-mapped
* VA==PA all at once. But pmap_copy_page() and pmap_zero_page() will have
* this problem, too.
*/
#define PMAP_MAP_POOLPAGE(pa) (pa)
#define PMAP_UNMAP_POOLPAGE(pa) (pa)
#define vtophys(va) pmap_kextract(((vm_offset_t) (va)))
extern pte_t PTmap[];
#define vtopte(x) (PTmap + powerpc_btop(x))
static __inline vm_offset_t
pmap_kextract(vm_offset_t va)
{
/* XXX: coming soon... */
return (0);
}
#endif /* _KERNEL */
#endif /* LOCORE */
#endif /* _MACHINE_PMAP_H_ */
#endif /* !_MACHINE_PMAP_H_ */

View File

@ -45,6 +45,10 @@ struct pte {
u_int pte_hi;
u_int pte_lo;
};
struct pteg {
struct pte pt[8];
};
#endif /* LOCORE */
/* High word: */
#define PTE_VALID 0x80000000
@ -61,8 +65,12 @@ struct pte {
#define PTE_M 0x00000010
#define PTE_G 0x00000008
#define PTE_PP 0x00000003
#define PTE_RO 0x00000003
#define PTE_RW 0x00000002
#define PTE_SO 0x00000000 /* Super. Only (U: XX, S: RW) */
#define PTE_SW 0x00000001 /* Super. Write-Only (U: RO, S: RW) */
#define PTE_BW 0x00000002 /* Supervisor (U: RW, S: RW) */
#define PTE_BR 0x00000003 /* Both Read Only (U: RO, S: RO) */
#define PTE_RW PTE_BW
#define PTE_RO PTE_BR
#ifndef LOCORE
typedef struct pte pte_t;

44
sys/powerpc/include/sr.h Normal file
View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2002 Benno Rice.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_SR_H_
#define _MACHINE_SR_H_
/*
* Bit definitions for segment registers.
*
* PowerPC Microprocessor Family: The Programming Environments for 32-bit
* Microprocessors, section 2.3.5
*/
#define SR_TYPE 0x80000000 /* Type selector */
#define SR_KS 0x40000000 /* Supervisor-state protection key */
#define SR_KP 0x20000000 /* User-state protection key */
#define SR_N 0x10000000 /* No-execute protection */
#define SR_VSID_MASK 0x00ffffff /* Virtual Segment ID mask */
#endif /* !_MACHINE_SR_H_ */

View File

@ -37,6 +37,7 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/resourcevar.h>
/*

View File

@ -64,7 +64,7 @@
#include <machine/trap.h>
#include <machine/param.h>
#include <machine/pmap.h>
#include <machine/sr.h>
#include <machine/psl.h>
#include <machine/asm.h>
@ -984,7 +984,7 @@ s_dsitrap:
mfctr 31 /* & CTR */
mfdar 3
s_pte_spill:
bl pte_spill /* try a spill */
bl pmap_pte_spill /* try a spill */
or. 3,3,3
mtctr 31 /* restore CTR */
mtlr 30 /* and trap type */
@ -1071,8 +1071,8 @@ s_isitrap:
stw 4,12(1); \
stw 3,8(1); \
/* interrupts are recoverable here, and enable translation */ \
lis 3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h; \
ori 3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l; \
lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \
ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \
mtsr KERNEL_SR,3; \
mfmsr 5; \
ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \

View File

@ -64,7 +64,7 @@
#include <machine/trap.h>
#include <machine/param.h>
#include <machine/pmap.h>
#include <machine/sr.h>
#include <machine/psl.h>
#include <machine/asm.h>
@ -984,7 +984,7 @@ s_dsitrap:
mfctr 31 /* & CTR */
mfdar 3
s_pte_spill:
bl pte_spill /* try a spill */
bl pmap_pte_spill /* try a spill */
or. 3,3,3
mtctr 31 /* restore CTR */
mtlr 30 /* and trap type */
@ -1071,8 +1071,8 @@ s_isitrap:
stw 4,12(1); \
stw 3,8(1); \
/* interrupts are recoverable here, and enable translation */ \
lis 3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h; \
ori 3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l; \
lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \
ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \
mtsr KERNEL_SR,3; \
mfmsr 5; \
ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \

View File

@ -116,8 +116,12 @@ int cold = 1;
struct mtx sched_lock;
struct mtx Giant;
struct user *proc0uarea;
vm_offset_t proc0kstack;
char pcpu0[PAGE_SIZE];
char uarea0[UAREA_PAGES * PAGE_SIZE];
struct trapframe frame0;
vm_offset_t kstack0;
vm_offset_t kstack0_phys;
char machine[] = "powerpc";
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
@ -156,17 +160,11 @@ sysctl_hw_physmem(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD,
0, 0, sysctl_hw_physmem, "IU", "");
struct msgbuf *msgbufp = 0;
int Maxmem = 0;
long dumplo;
vm_offset_t phys_avail[10];
static int chosen;
static struct trapframe proc0_tf;
struct pmap ofw_pmap;
extern int ofmsr;
@ -262,6 +260,9 @@ identifycpu()
version = pvr >> 16;
revision = pvr & 0xffff;
switch (version) {
case 0x0000:
sprintf(model, "Simulator (psim)");
break;
case 0x0001:
sprintf(model, "601");
break;
@ -346,6 +347,77 @@ extern ddblow, ddbsize;
extern ipkdblow, ipkdbsize;
#endif
void
powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
{
struct pcpu *pc;
vm_offset_t off;
/*
* Initialize the console before printing anything.
*/
cninit();
/*
* Initialize tunables.
*/
init_param1();
init_param2(physmem);
/*
* Initialise virtual memory.
*/
ofmsr |= PSL_IR | PSL_DR;
pmap_bootstrap(startkernel, endkernel);
/*
* XXX: Initialize the interrupt tables.
*/
bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
/*
* Initialize proc0.
*/
proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0);
/* proc0.p_md.md_utrap = NULL; */
proc0.p_uarea = (struct user *)uarea0;
proc0.p_stats = &proc0.p_uarea->u_stats;
thread0.td_kstack = kstack0;
thread0.td_pcb = (struct pcb *)
(thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
/* frame0.tf_tstate = TSTATE_IE | TSTATE_PEF; */
thread0.td_frame = &frame0;
LIST_INIT(&thread0.td_contested);
/*
* Set up per-cpu data.
*/
pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1;
pcpu_init(pc, 0, sizeof(struct pcpu));
pc->pc_curthread = &thread0;
pc->pc_curpcb = thread0.td_pcb;
/* pc->pc_mid = mid; */
__asm __volatile("mtsprg 0, %0" :: "r"(pc));
/*
* Map and initialise the message buffer.
*/
for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
msgbufinit(msgbufp, MSGBUF_SIZE);
/*
* Initialize mutexes.
*/
mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE);
mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE);
mtx_init(&proc0.p_mtx, "process lock", MTX_DEF);
mtx_lock(&Giant);
}
#if 0 /* XXX: Old powerpc_init */
void
powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
{
@ -598,6 +670,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args)
thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
thread0.td_frame = &proc0_tf;
}
#endif
static int N_mapping;
static struct {
@ -916,8 +989,7 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
}
void
enable_fpu(pcb)
struct pcb *pcb;
enable_fpu(struct pcb *pcb)
{
int msr, scratch;
@ -964,8 +1036,7 @@ enable_fpu(pcb)
}
void
save_fpu(pcb)
struct pcb *pcb;
save_fpu(struct pcb *pcb)
{
int msr, scratch;

File diff suppressed because it is too large Load Diff

View File

@ -48,12 +48,18 @@ static const char rcsid[] =
#include <dev/ofw/openfirm.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <machine/powerpc.h>
#define OFMEM_REGIONS 32
static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
extern long ofmsr;
extern struct pmap ofw_pmap;
extern int pmap_bootstrapped;
static int (*ofwcall)(void *);
/*
@ -95,8 +101,48 @@ openfirmware(void *args)
{
long oldmsr;
int result;
u_int srsave[16];
__asm( "\t"
if (pmap_bootstrapped) {
__asm __volatile("mfsr %0,0" : "=r"(srsave[0]));
__asm __volatile("mfsr %0,1" : "=r"(srsave[1]));
__asm __volatile("mfsr %0,2" : "=r"(srsave[2]));
__asm __volatile("mfsr %0,3" : "=r"(srsave[3]));
__asm __volatile("mfsr %0,4" : "=r"(srsave[4]));
__asm __volatile("mfsr %0,5" : "=r"(srsave[5]));
__asm __volatile("mfsr %0,6" : "=r"(srsave[6]));
__asm __volatile("mfsr %0,7" : "=r"(srsave[7]));
__asm __volatile("mfsr %0,8" : "=r"(srsave[8]));
__asm __volatile("mfsr %0,9" : "=r"(srsave[9]));
__asm __volatile("mfsr %0,10" : "=r"(srsave[10]));
__asm __volatile("mfsr %0,11" : "=r"(srsave[11]));
__asm __volatile("mfsr %0,12" : "=r"(srsave[12]));
__asm __volatile("mfsr %0,13" : "=r"(srsave[13]));
__asm __volatile("mfsr %0,14" : "=r"(srsave[14]));
__asm __volatile("mfsr %0,15" : "=r"(srsave[15]));
__asm __volatile("mtsr 0,%0" :: "r"(ofw_pmap.pm_sr[0]));
__asm __volatile("mtsr 1,%0" :: "r"(ofw_pmap.pm_sr[1]));
__asm __volatile("mtsr 2,%0" :: "r"(ofw_pmap.pm_sr[2]));
__asm __volatile("mtsr 3,%0" :: "r"(ofw_pmap.pm_sr[3]));
__asm __volatile("mtsr 4,%0" :: "r"(ofw_pmap.pm_sr[4]));
__asm __volatile("mtsr 5,%0" :: "r"(ofw_pmap.pm_sr[5]));
__asm __volatile("mtsr 6,%0" :: "r"(ofw_pmap.pm_sr[6]));
__asm __volatile("mtsr 7,%0" :: "r"(ofw_pmap.pm_sr[7]));
__asm __volatile("mtsr 8,%0" :: "r"(ofw_pmap.pm_sr[8]));
__asm __volatile("mtsr 9,%0" :: "r"(ofw_pmap.pm_sr[9]));
__asm __volatile("mtsr 10,%0" :: "r"(ofw_pmap.pm_sr[10]));
__asm __volatile("mtsr 11,%0" :: "r"(ofw_pmap.pm_sr[11]));
__asm __volatile("mtsr 12,%0" :: "r"(ofw_pmap.pm_sr[12]));
__asm __volatile("mtsr 13,%0" :: "r"(ofw_pmap.pm_sr[13]));
__asm __volatile("mtsr 14,%0" :: "r"(ofw_pmap.pm_sr[14]));
__asm __volatile("mtsr 15,%0" :: "r"(ofw_pmap.pm_sr[15]));
}
ofmsr |= PSL_RI|PSL_EE;
__asm __volatile( "\t"
"sync\n\t"
"mfmsr %0\n\t"
"mtmsr %1\n\t"
"isync\n"
@ -112,6 +158,27 @@ openfirmware(void *args)
: : "r" (oldmsr)
);
if (pmap_bootstrapped) {
__asm __volatile("mtsr 0,%0" :: "r"(srsave[0]));
__asm __volatile("mtsr 1,%0" :: "r"(srsave[1]));
__asm __volatile("mtsr 2,%0" :: "r"(srsave[2]));
__asm __volatile("mtsr 3,%0" :: "r"(srsave[3]));
__asm __volatile("mtsr 4,%0" :: "r"(srsave[4]));
__asm __volatile("mtsr 5,%0" :: "r"(srsave[5]));
__asm __volatile("mtsr 6,%0" :: "r"(srsave[6]));
__asm __volatile("mtsr 7,%0" :: "r"(srsave[7]));
__asm __volatile("mtsr 8,%0" :: "r"(srsave[8]));
__asm __volatile("mtsr 9,%0" :: "r"(srsave[9]));
__asm __volatile("mtsr 10,%0" :: "r"(srsave[10]));
__asm __volatile("mtsr 11,%0" :: "r"(srsave[11]));
__asm __volatile("mtsr 12,%0" :: "r"(srsave[12]));
__asm __volatile("mtsr 13,%0" :: "r"(srsave[13]));
__asm __volatile("mtsr 14,%0" :: "r"(srsave[14]));
__asm __volatile("mtsr 15,%0" :: "r"(srsave[15]));
__asm __volatile("sync");
}
return (result);
}

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@
#include <machine/trap.h>
#include <machine/param.h>
#include <machine/pmap.h>
#include <machine/sr.h>
#include <machine/psl.h>
#include <machine/asm.h>

View File

@ -62,7 +62,7 @@
#include <machine/trap.h>
#include <machine/param.h>
#include <machine/pmap.h>
#include <machine/sr.h>
#include <machine/psl.h>
#include <machine/asm.h>

View File

@ -467,7 +467,7 @@ trap_pfault(struct trapframe *frame, int user)
return (SIGSEGV);
map = kernel_map;
} else {
sr_t user_sr;
u_int user_sr;
if (p->p_vmspace == NULL)
return (SIGSEGV);

View File

@ -126,9 +126,10 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
struct trapframe *tf;
struct callframe *cf;
struct switchframe *sf;
caddr_t stktop1, stktop2;
struct pcb *pcb2;
struct pcb *pcb;
KASSERT(td1 == curthread || td1 == thread0,
("cpu_fork: p1 not curproc and not proc0"));
CTR3(KTR_PROC, "cpu_fork: called td1=%08x p2=%08x flags=%x", (u_int)td1, (u_int)p2, flags);
if ((flags & RFPROC) == 0)
@ -136,39 +137,42 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
p1 = td1->td_proc;
/* Point the pcb to the top of the stack */
pcb2 = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
td2->td_pcb = pcb2;
pcb = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
sizeof(struct pcb));
td2->td_pcb = pcb;
/* Copy p1's pcb. */
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
/* Copy the pcb */
bcopy(td1->td_pcb, pcb, sizeof(struct pcb));
/*
* Create a new fresh stack for the new process.
* Create a fresh stack for the new process.
* Copy the trap frame for the return to user mode as if from a
* syscall. This copies most of the user mode register values.
*/
td2->td_frame = (struct trapframe *)td2->td_pcb - 1;
bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe));
stktop2 = (caddr_t)td2->td_frame;
tf = (struct trapframe *)pcb - 1;
bcopy(td1->td_frame, tf, sizeof(*tf));
cf = (struct callframe *)stktop2;
/* XXX: Set up trap frame? */
td2->td_frame = tf;
/*
* There happens to be a callframe, too.
*/
cf = (struct callframe *)tf - 1;
cf->lr = (int)fork_trampoline;
stktop2 -= 16;
cf = (struct callframe *)stktop2;
cf->r31 = (register_t)fork_return;
cf->r30 = (register_t)td2;
stktop2 -= roundup(sizeof *sf, 16);
sf = (struct switchframe *)stktop2;
bzero((void *)sf, sizeof *sf);
/*
* Below that, we allocate the switch frame.
*/
sf = (struct switchframe *)cf - 1;
sf->sp = (int)cf;
sf->user_sr = kernel_pmap->pm_sr[USER_SR];
pcb2->pcb_sp = (int)stktop2;
pcb2->pcb_spl = 0;
pcb->pcb_sp = (int)sf;
/*
* Now cpu_switch() can schedule the new process.
*/
}
/*
@ -233,10 +237,10 @@ cpu_coredump(td, vp, cred)
struct vnode *vp;
struct ucred *cred;
{
struct proc *p = td->td_proc;
return (vn_rdwr(UIO_WRITE, vp, (caddr_t)p->p_uarea, ctob(UAREA_PAGES),
(off_t)0, UIO_SYSSPACE, IO_UNIT, cred, (int *)NULL, p));
return (vn_rdwr(UIO_WRITE, vp, (caddr_t)td->td_proc->p_uarea,
ctob(UAREA_PAGES), (off_t)0, UIO_SYSSPACE, IO_UNIT, cred,
(int *)NULL, td));
}
/*