summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2002-02-28 03:24:07 +0000
committerbenno <benno@FreeBSD.org>2002-02-28 03:24:07 +0000
commita0268a06222fcbb69243c6e67fe1741ac3a77194 (patch)
treeb7f558b1545ed5a0d8ad186ce6dba3e85f00a3dc /sys/powerpc
parent778f777d9dcd70311e383a7b20a4b32a146a6790 (diff)
downloadFreeBSD-src-a0268a06222fcbb69243c6e67fe1741ac3a77194.zip
FreeBSD-src-a0268a06222fcbb69243c6e67fe1741ac3a77194.tar.gz
Make fork work, at least for kthreads. Switching still has some issues.
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/aim/locore.S18
-rw-r--r--sys/powerpc/aim/swtch.S11
-rw-r--r--sys/powerpc/aim/vm_machdep.c30
-rw-r--r--sys/powerpc/include/frame.h13
-rw-r--r--sys/powerpc/include/pcb.h21
-rw-r--r--sys/powerpc/powerpc/genassym.c6
-rw-r--r--sys/powerpc/powerpc/locore.S18
-rw-r--r--sys/powerpc/powerpc/locore.s18
-rw-r--r--sys/powerpc/powerpc/swtch.S11
-rw-r--r--sys/powerpc/powerpc/swtch.s11
-rw-r--r--sys/powerpc/powerpc/vm_machdep.c30
11 files changed, 77 insertions, 110 deletions
diff --git a/sys/powerpc/aim/locore.S b/sys/powerpc/aim/locore.S
index 76fc3aa..79c575d 100644
--- a/sys/powerpc/aim/locore.S
+++ b/sys/powerpc/aim/locore.S
@@ -940,24 +940,6 @@ s_trap:
rfi
/*
- * Child comes here at the end of a fork.
- * Mostly similar to the above.
- */
- .globl fork_trampoline
-fork_trampoline:
- xor 3,3,3
-#if 0 /* XXX */
- bl lcsplx
-#endif
- mtlr 31
- mr 3,30
- blrl /* jump indirect to r31 */
- mr 3,30
- bl ast
- FRAME_LEAVE(tempsave)
- rfi
-
-/*
* DSI second stage fault handler
*/
s_dsitrap:
diff --git a/sys/powerpc/aim/swtch.S b/sys/powerpc/aim/swtch.S
index 00bdbb3..828c6cd 100644
--- a/sys/powerpc/aim/swtch.S
+++ b/sys/powerpc/aim/swtch.S
@@ -121,3 +121,14 @@ ENTRY(savectx)
mfcr %r4 /* Save the condition register */
stw %r4,PCB_CONTEXT(%r3)
blr
+
+/*
+ * fork_trampoline()
+ * Set up the return from cpu_fork()
+ */
+ENTRY(fork_trampoline)
+ lwz %r3,CF_FUNC(1)
+ lwz %r4,CF_ARG0(1)
+ lwz %r5,CF_ARG1(1)
+ bl fork_exit
+ rfi
diff --git a/sys/powerpc/aim/vm_machdep.c b/sys/powerpc/aim/vm_machdep.c
index 6958373..36345ec 100644
--- a/sys/powerpc/aim/vm_machdep.c
+++ b/sys/powerpc/aim/vm_machdep.c
@@ -128,7 +128,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
struct switchframe *sf;
struct pcb *pcb;
- KASSERT(td1 == curthread || td1 == thread0,
+ 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);
@@ -137,8 +137,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
p1 = td1->td_proc;
- pcb = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
- sizeof(struct pcb));
+ pcb = (struct pcb *)((td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
+ sizeof(struct pcb)) & ~0x2fU);
td2->td_pcb = pcb;
/* Copy the pcb */
@@ -149,7 +149,6 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
* Copy the trap frame for the return to user mode as if from a
* syscall. This copies most of the user mode register values.
*/
-
tf = (struct trapframe *)pcb - 1;
bcopy(td1->td_frame, tf, sizeof(*tf));
@@ -157,18 +156,13 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
td2->td_frame = tf;
- /*
- * There happens to be a callframe, too.
- */
cf = (struct callframe *)tf - 1;
- cf->lr = (int)fork_trampoline;
+ cf->cf_func = (register_t)fork_return;
+ cf->cf_arg0 = (register_t)td2;
+ cf->cf_arg1 = (register_t)tf;
- /*
- * Below that, we allocate the switch frame.
- */
- sf = (struct switchframe *)cf - 1;
- sf->sp = (int)cf;
- pcb->pcb_sp = (int)sf;
+ pcb->pcb_sp = (register_t)cf;
+ pcb->pcb_lr = (register_t)fork_trampoline;
/*
* Now cpu_switch() can schedule the new process.
@@ -187,17 +181,15 @@ cpu_set_fork_handler(td, func, arg)
void (*func) __P((void *));
void *arg;
{
- struct switchframe *sf;
struct callframe *cf;
CTR3(KTR_PROC, "cpu_set_fork_handler: called with td=%08x func=%08x arg=%08x",
(u_int)td, (u_int)func, (u_int)arg);
- sf = (struct switchframe *)td->td_pcb->pcb_sp;
- cf = (struct callframe *)sf->sp;
+ cf = (struct callframe *)td->td_pcb->pcb_sp;
- cf->r31 = (register_t)func;
- cf->r30 = (register_t)arg;
+ cf->cf_func = (register_t)func;
+ cf->cf_arg0 = (register_t)arg;
}
/*
diff --git a/sys/powerpc/include/frame.h b/sys/powerpc/include/frame.h
index 3865de4..72dbd9f 100644
--- a/sys/powerpc/include/frame.h
+++ b/sys/powerpc/include/frame.h
@@ -67,9 +67,9 @@ struct trapframe {
struct switchframe {
register_t sp;
- int fill;
- int user_sr;
- int cr;
+ register_t fill;
+ register_t user_sr;
+ register_t cr;
register_t fixreg2;
register_t fixreg[19]; /* R13-R31 */
};
@@ -85,10 +85,9 @@ struct clockframe {
* Call frame for PowerPC used during fork.
*/
struct callframe {
- register_t sp;
- register_t lr;
- register_t r30;
- register_t r31;
+ register_t cf_func;
+ register_t cf_arg0;
+ register_t cf_arg1;
};
#endif /* _MACHINE_FRAME_H_ */
diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h
index 98b6fa9..fbd7cbf 100644
--- a/sys/powerpc/include/pcb.h
+++ b/sys/powerpc/include/pcb.h
@@ -38,18 +38,19 @@
typedef int faultbuf[23];
struct pcb {
- u_int32_t pcb_context[18]; /* non-volatile r14-r31 */
- u_int32_t pcb_cr; /* Condition register */
- struct pmap *pcb_pm; /* pmap of our vmspace */
- struct pmap *pcb_pmreal; /* real address of above */
- register_t pcb_sp; /* saved SP */
- int pcb_spl; /* saved SPL */
- faultbuf *pcb_onfault; /* For use during copyin/copyout */
- int pcb_flags;
+ register_t pcb_context[18]; /* non-volatile r14-r31 */
+ register_t pcb_cr; /* Condition register */
+ register_t pcb_sp; /* stack pointer */
+ register_t pcb_lr; /* link register */
+ struct pmap *pcb_pm; /* pmap of our vmspace */
+ struct pmap *pcb_pmreal; /* real address of above */
+ faultbuf *pcb_onfault; /* For use during
+ copyin/copyout */
+ int pcb_flags;
#define PCB_FPU 1 /* Process had FPU initialized */
struct fpu {
- double fpr[32];
- double fpscr; /* FPSCR stored as double for easier access */
+ double fpr[32];
+ double fpscr; /* FPSCR stored as double for easier access */
} pcb_fpu; /* Floating point processor */
};
diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c
index f0b28d4..c8a484b 100644
--- a/sys/powerpc/powerpc/genassym.c
+++ b/sys/powerpc/powerpc/genassym.c
@@ -86,11 +86,15 @@ ASSYM(FRAME_EXC, offsetof(struct trapframe, exc));
ASSYM(SFRAMELEN, roundup(sizeof(struct switchframe), 16));
+ASSYM(CF_FUNC, offsetof(struct callframe, cf_func));
+ASSYM(CF_ARG0, offsetof(struct callframe, cf_arg0));
+ASSYM(CF_ARG1, offsetof(struct callframe, cf_arg1));
+
ASSYM(PCB_CONTEXT, offsetof(struct pcb, pcb_context));
ASSYM(PCB_CR, offsetof(struct pcb, pcb_cr));
ASSYM(PCB_PMR, offsetof(struct pcb, pcb_pmreal));
ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
-ASSYM(PCB_SPL, offsetof(struct pcb, pcb_spl));
+ASSYM(PCB_LR, offsetof(struct pcb, pcb_lr));
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
diff --git a/sys/powerpc/powerpc/locore.S b/sys/powerpc/powerpc/locore.S
index 76fc3aa..79c575d 100644
--- a/sys/powerpc/powerpc/locore.S
+++ b/sys/powerpc/powerpc/locore.S
@@ -940,24 +940,6 @@ s_trap:
rfi
/*
- * Child comes here at the end of a fork.
- * Mostly similar to the above.
- */
- .globl fork_trampoline
-fork_trampoline:
- xor 3,3,3
-#if 0 /* XXX */
- bl lcsplx
-#endif
- mtlr 31
- mr 3,30
- blrl /* jump indirect to r31 */
- mr 3,30
- bl ast
- FRAME_LEAVE(tempsave)
- rfi
-
-/*
* DSI second stage fault handler
*/
s_dsitrap:
diff --git a/sys/powerpc/powerpc/locore.s b/sys/powerpc/powerpc/locore.s
index 76fc3aa..79c575d 100644
--- a/sys/powerpc/powerpc/locore.s
+++ b/sys/powerpc/powerpc/locore.s
@@ -940,24 +940,6 @@ s_trap:
rfi
/*
- * Child comes here at the end of a fork.
- * Mostly similar to the above.
- */
- .globl fork_trampoline
-fork_trampoline:
- xor 3,3,3
-#if 0 /* XXX */
- bl lcsplx
-#endif
- mtlr 31
- mr 3,30
- blrl /* jump indirect to r31 */
- mr 3,30
- bl ast
- FRAME_LEAVE(tempsave)
- rfi
-
-/*
* DSI second stage fault handler
*/
s_dsitrap:
diff --git a/sys/powerpc/powerpc/swtch.S b/sys/powerpc/powerpc/swtch.S
index 00bdbb3..828c6cd 100644
--- a/sys/powerpc/powerpc/swtch.S
+++ b/sys/powerpc/powerpc/swtch.S
@@ -121,3 +121,14 @@ ENTRY(savectx)
mfcr %r4 /* Save the condition register */
stw %r4,PCB_CONTEXT(%r3)
blr
+
+/*
+ * fork_trampoline()
+ * Set up the return from cpu_fork()
+ */
+ENTRY(fork_trampoline)
+ lwz %r3,CF_FUNC(1)
+ lwz %r4,CF_ARG0(1)
+ lwz %r5,CF_ARG1(1)
+ bl fork_exit
+ rfi
diff --git a/sys/powerpc/powerpc/swtch.s b/sys/powerpc/powerpc/swtch.s
index 00bdbb3..828c6cd 100644
--- a/sys/powerpc/powerpc/swtch.s
+++ b/sys/powerpc/powerpc/swtch.s
@@ -121,3 +121,14 @@ ENTRY(savectx)
mfcr %r4 /* Save the condition register */
stw %r4,PCB_CONTEXT(%r3)
blr
+
+/*
+ * fork_trampoline()
+ * Set up the return from cpu_fork()
+ */
+ENTRY(fork_trampoline)
+ lwz %r3,CF_FUNC(1)
+ lwz %r4,CF_ARG0(1)
+ lwz %r5,CF_ARG1(1)
+ bl fork_exit
+ rfi
diff --git a/sys/powerpc/powerpc/vm_machdep.c b/sys/powerpc/powerpc/vm_machdep.c
index 6958373..36345ec 100644
--- a/sys/powerpc/powerpc/vm_machdep.c
+++ b/sys/powerpc/powerpc/vm_machdep.c
@@ -128,7 +128,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
struct switchframe *sf;
struct pcb *pcb;
- KASSERT(td1 == curthread || td1 == thread0,
+ 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);
@@ -137,8 +137,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
p1 = td1->td_proc;
- pcb = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
- sizeof(struct pcb));
+ pcb = (struct pcb *)((td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
+ sizeof(struct pcb)) & ~0x2fU);
td2->td_pcb = pcb;
/* Copy the pcb */
@@ -149,7 +149,6 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
* Copy the trap frame for the return to user mode as if from a
* syscall. This copies most of the user mode register values.
*/
-
tf = (struct trapframe *)pcb - 1;
bcopy(td1->td_frame, tf, sizeof(*tf));
@@ -157,18 +156,13 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
td2->td_frame = tf;
- /*
- * There happens to be a callframe, too.
- */
cf = (struct callframe *)tf - 1;
- cf->lr = (int)fork_trampoline;
+ cf->cf_func = (register_t)fork_return;
+ cf->cf_arg0 = (register_t)td2;
+ cf->cf_arg1 = (register_t)tf;
- /*
- * Below that, we allocate the switch frame.
- */
- sf = (struct switchframe *)cf - 1;
- sf->sp = (int)cf;
- pcb->pcb_sp = (int)sf;
+ pcb->pcb_sp = (register_t)cf;
+ pcb->pcb_lr = (register_t)fork_trampoline;
/*
* Now cpu_switch() can schedule the new process.
@@ -187,17 +181,15 @@ cpu_set_fork_handler(td, func, arg)
void (*func) __P((void *));
void *arg;
{
- struct switchframe *sf;
struct callframe *cf;
CTR3(KTR_PROC, "cpu_set_fork_handler: called with td=%08x func=%08x arg=%08x",
(u_int)td, (u_int)func, (u_int)arg);
- sf = (struct switchframe *)td->td_pcb->pcb_sp;
- cf = (struct callframe *)sf->sp;
+ cf = (struct callframe *)td->td_pcb->pcb_sp;
- cf->r31 = (register_t)func;
- cf->r30 = (register_t)arg;
+ cf->cf_func = (register_t)func;
+ cf->cf_arg0 = (register_t)arg;
}
/*
OpenPOWER on IntegriCloud