Cleanup up ARM *frame structures...
- Eliminate unused irqframe - Eliminate unused saframe - Instead of splitting r4-sp storage between the stack and switchframe, just put all the registers in switchframe and eliminate the un_32 struct. Submitted by: Svatopluk Kraus <onwahe@gmail.com>, Michal Meloun <meloun@miracle.cz>
This commit is contained in:
parent
04fef9c446
commit
c4c27bc97f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=276190
@ -72,20 +72,12 @@ kgdb_trgt_fetch_registers(int regno __unused)
|
||||
warnx("kvm_read: %s", kvm_geterr(kvm));
|
||||
memset(&pcb, 0, sizeof(pcb));
|
||||
}
|
||||
for (i = ARM_A1_REGNUM + 8; i <= ARM_SP_REGNUM; i++) {
|
||||
supply_register(i, (char *)&pcb.un_32.pcb32_r8 +
|
||||
(i - (ARM_A1_REGNUM + 8 )) * 4);
|
||||
for (i = ARM_A1_REGNUM + 4; i <= ARM_SP_REGNUM; i++) {
|
||||
supply_register(i, (char *)&pcb.pcb_regs.sf_r4 +
|
||||
(i - (ARM_A1_REGNUM + 4 )) * 4);
|
||||
}
|
||||
if (pcb.un_32.pcb32_sp != 0) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (kvm_read(kvm, pcb.un_32.pcb32_sp + (i) * 4,
|
||||
®, 4) != 4) {
|
||||
warnx("kvm_read: %s", kvm_geterr(kvm));
|
||||
break;
|
||||
}
|
||||
supply_register(ARM_A1_REGNUM + 4 + i, (char *)®);
|
||||
}
|
||||
if (kvm_read(kvm, pcb.un_32.pcb32_sp + 4 * 4, ®, 4) != 4)
|
||||
if (pcb.pcb_regs.sf_sp != 0) {
|
||||
if (kvm_read(kvm, pcb.pcb_regs.sf_sp + 4 * 4, ®, 4) != 4)
|
||||
warnx("kvm_read :%s", kvm_geterr(kvm));
|
||||
else
|
||||
supply_register(ARM_PC_REGNUM, (char *)®);
|
||||
|
@ -609,14 +609,14 @@ db_trace_thread(struct thread *thr, int count)
|
||||
ctx = kdb_thr_ctx(thr);
|
||||
|
||||
#ifdef __ARM_EABI__
|
||||
state.registers[FP] = ctx->un_32.pcb32_r11;
|
||||
state.registers[SP] = ctx->un_32.pcb32_sp;
|
||||
state.registers[LR] = ctx->un_32.pcb32_lr;
|
||||
state.registers[PC] = ctx->un_32.pcb32_pc;
|
||||
state.registers[FP] = ctx->pcb_regs.sf_r11;
|
||||
state.registers[SP] = ctx->pcb_regs.sf_sp;
|
||||
state.registers[LR] = ctx->pcb_regs.sf_lr;
|
||||
state.registers[PC] = ctx->pcb_regs.sf_pc;
|
||||
|
||||
db_stack_trace_cmd(&state);
|
||||
#else
|
||||
db_stack_trace_cmd(ctx->un_32.pcb32_r11, -1, TRUE);
|
||||
db_stack_trace_cmd(ctx->pcb_regs.sf_r11, -1, TRUE);
|
||||
#endif
|
||||
} else
|
||||
db_trace_self();
|
||||
|
@ -67,22 +67,26 @@ gdb_cpu_getreg(int regnum, size_t *regsz)
|
||||
}
|
||||
|
||||
switch (regnum) {
|
||||
case 8: return (&kdb_thrctx->un_32.pcb32_r8);
|
||||
case 9: return (&kdb_thrctx->un_32.pcb32_r9);
|
||||
case 10: return (&kdb_thrctx->un_32.pcb32_r10);
|
||||
case 11: return (&kdb_thrctx->un_32.pcb32_r11);
|
||||
case 12: return (&kdb_thrctx->un_32.pcb32_r12);
|
||||
case 13: stacktest = kdb_thrctx->un_32.pcb32_sp + 5 * 4;
|
||||
case 4: return (&kdb_thrctx->pcb_regs.sf_r4);
|
||||
case 5: return (&kdb_thrctx->pcb_regs.sf_r5);
|
||||
case 6: return (&kdb_thrctx->pcb_regs.sf_r6);
|
||||
case 7: return (&kdb_thrctx->pcb_regs.sf_r7);
|
||||
case 8: return (&kdb_thrctx->pcb_regs.sf_r8);
|
||||
case 9: return (&kdb_thrctx->pcb_regs.sf_r9);
|
||||
case 10: return (&kdb_thrctx->pcb_regs.sf_r10);
|
||||
case 11: return (&kdb_thrctx->pcb_regs.sf_r11);
|
||||
case 12: return (&kdb_thrctx->pcb_regs.sf_r12);
|
||||
case 13: stacktest = kdb_thrctx->pcb_regs.sf_sp + 5 * 4;
|
||||
return (&stacktest);
|
||||
case 15:
|
||||
/*
|
||||
* On context switch, the PC is not put in the PCB, but
|
||||
* we can retrieve it from the stack.
|
||||
*/
|
||||
if (kdb_thrctx->un_32.pcb32_sp > KERNBASE) {
|
||||
kdb_thrctx->un_32.pcb32_pc = *(register_t *)
|
||||
(kdb_thrctx->un_32.pcb32_sp + 4 * 4);
|
||||
return (&kdb_thrctx->un_32.pcb32_pc);
|
||||
if (kdb_thrctx->pcb_regs.sf_sp > KERNBASE) {
|
||||
kdb_thrctx->pcb_regs.sf_pc = *(register_t *)
|
||||
(kdb_thrctx->pcb_regs.sf_sp + 4 * 4);
|
||||
return (&kdb_thrctx->pcb_regs.sf_pc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,13 +63,18 @@ ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
|
||||
ASSYM(PCB_PAGEDIR, offsetof(struct pcb, pcb_pagedir));
|
||||
ASSYM(PCB_L1VEC, offsetof(struct pcb, pcb_l1vec));
|
||||
ASSYM(PCB_PL1VEC, offsetof(struct pcb, pcb_pl1vec));
|
||||
ASSYM(PCB_R8, offsetof(struct pcb, un_32.pcb32_r8));
|
||||
ASSYM(PCB_R9, offsetof(struct pcb, un_32.pcb32_r9));
|
||||
ASSYM(PCB_R10, offsetof(struct pcb, un_32.pcb32_r10));
|
||||
ASSYM(PCB_R11, offsetof(struct pcb, un_32.pcb32_r11));
|
||||
ASSYM(PCB_R12, offsetof(struct pcb, un_32.pcb32_r12));
|
||||
ASSYM(PCB_PC, offsetof(struct pcb, un_32.pcb32_pc));
|
||||
ASSYM(PCB_SP, offsetof(struct pcb, un_32.pcb32_sp));
|
||||
ASSYM(PCB_R4, offsetof(struct pcb, pcb_regs.sf_r4));
|
||||
ASSYM(PCB_R5, offsetof(struct pcb, pcb_regs.sf_r5));
|
||||
ASSYM(PCB_R6, offsetof(struct pcb, pcb_regs.sf_r6));
|
||||
ASSYM(PCB_R7, offsetof(struct pcb, pcb_regs.sf_r7));
|
||||
ASSYM(PCB_R8, offsetof(struct pcb, pcb_regs.sf_r8));
|
||||
ASSYM(PCB_R9, offsetof(struct pcb, pcb_regs.sf_r9));
|
||||
ASSYM(PCB_R10, offsetof(struct pcb, pcb_regs.sf_r10));
|
||||
ASSYM(PCB_R11, offsetof(struct pcb, pcb_regs.sf_r11));
|
||||
ASSYM(PCB_R12, offsetof(struct pcb, pcb_regs.sf_r12));
|
||||
ASSYM(PCB_SP, offsetof(struct pcb, pcb_regs.sf_sp));
|
||||
ASSYM(PCB_LR, offsetof(struct pcb, pcb_regs.sf_lr));
|
||||
ASSYM(PCB_PC, offsetof(struct pcb, pcb_regs.sf_pc));
|
||||
|
||||
ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
|
||||
ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
|
||||
|
@ -378,7 +378,7 @@ cpu_startup(void *dummy)
|
||||
|
||||
bufinit();
|
||||
vm_pager_bufferinit();
|
||||
pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack +
|
||||
pcb->pcb_regs.sf_sp = (u_int)thread0.td_kstack +
|
||||
USPACE_SVC_STACK_TOP;
|
||||
vector_page_setprot(VM_PROT_READ);
|
||||
pmap_set_pcb_pagedir(pmap_kernel(), pcb);
|
||||
@ -770,14 +770,18 @@ sys_sigreturn(td, uap)
|
||||
void
|
||||
makectx(struct trapframe *tf, struct pcb *pcb)
|
||||
{
|
||||
pcb->un_32.pcb32_r8 = tf->tf_r8;
|
||||
pcb->un_32.pcb32_r9 = tf->tf_r9;
|
||||
pcb->un_32.pcb32_r10 = tf->tf_r10;
|
||||
pcb->un_32.pcb32_r11 = tf->tf_r11;
|
||||
pcb->un_32.pcb32_r12 = tf->tf_r12;
|
||||
pcb->un_32.pcb32_pc = tf->tf_pc;
|
||||
pcb->un_32.pcb32_lr = tf->tf_usr_lr;
|
||||
pcb->un_32.pcb32_sp = tf->tf_usr_sp;
|
||||
pcb->pcb_regs.sf_r4 = tf->tf_r4;
|
||||
pcb->pcb_regs.sf_r5 = tf->tf_r5;
|
||||
pcb->pcb_regs.sf_r6 = tf->tf_r6;
|
||||
pcb->pcb_regs.sf_r7 = tf->tf_r7;
|
||||
pcb->pcb_regs.sf_r8 = tf->tf_r8;
|
||||
pcb->pcb_regs.sf_r9 = tf->tf_r9;
|
||||
pcb->pcb_regs.sf_r10 = tf->tf_r10;
|
||||
pcb->pcb_regs.sf_r11 = tf->tf_r11;
|
||||
pcb->pcb_regs.sf_r12 = tf->tf_r12;
|
||||
pcb->pcb_regs.sf_pc = tf->tf_pc;
|
||||
pcb->pcb_regs.sf_lr = tf->tf_usr_lr;
|
||||
pcb->pcb_regs.sf_sp = tf->tf_usr_sp;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -76,7 +76,7 @@ stack_save_td(struct stack *st, struct thread *td)
|
||||
* as it doesn't have a frame pointer, however it's value is not used
|
||||
* when building for EABI.
|
||||
*/
|
||||
frame = (u_int32_t *)td->td_pcb->un_32.pcb32_r11;
|
||||
frame = (u_int32_t *)td->td_pcb->pcb_regs.sf_r11;
|
||||
stack_zero(st);
|
||||
stack_capture(st, frame);
|
||||
}
|
||||
|
@ -116,6 +116,14 @@ __FBSDID("$FreeBSD$");
|
||||
.Lblocked_lock:
|
||||
.word _C_LABEL(blocked_lock)
|
||||
|
||||
/*
|
||||
* cpu_throw(oldtd, newtd)
|
||||
*
|
||||
* Remove current thread state, then select the next thread to run
|
||||
* and load its state.
|
||||
* r0 = oldtd
|
||||
* r1 = newtd
|
||||
*/
|
||||
ENTRY(cpu_throw)
|
||||
mov r5, r1
|
||||
|
||||
@ -144,7 +152,6 @@ ENTRY(cpu_throw)
|
||||
* r0 = Pointer to L1 slot for vector_page (or NULL)
|
||||
* r1 = lwp0's DACR
|
||||
* r5 = lwp0
|
||||
* r6 = exit func
|
||||
* r7 = lwp0's PCB
|
||||
* r9 = cpufuncs
|
||||
*/
|
||||
@ -181,25 +188,11 @@ ENTRY(cpu_throw)
|
||||
mov lr, pc
|
||||
ldr pc, [r9, #CF_CONTEXT_SWITCH]
|
||||
|
||||
/* Restore all the save registers */
|
||||
#ifndef _ARM_ARCH_5E
|
||||
add r1, r7, #PCB_R8
|
||||
ldmia r1, {r8-r13}
|
||||
#else
|
||||
ldr r8, [r7, #(PCB_R8)]
|
||||
ldr r9, [r7, #(PCB_R9)]
|
||||
ldr r10, [r7, #(PCB_R10)]
|
||||
ldr r11, [r7, #(PCB_R11)]
|
||||
ldr r12, [r7, #(PCB_R12)]
|
||||
ldr r13, [r7, #(PCB_SP)]
|
||||
#endif
|
||||
|
||||
GET_PCPU(r6, r4)
|
||||
/* Hook in a new pcb */
|
||||
str r7, [r6, #PC_CURPCB]
|
||||
/* We have a new curthread now so make a note it */
|
||||
add r6, r6, #PC_CURTHREAD
|
||||
str r5, [r6]
|
||||
str r5, [r6, #PC_CURTHREAD]
|
||||
#ifndef ARM_TP_ADDRESS
|
||||
mcr p15, 0, r5, c13, c0, 4
|
||||
#endif
|
||||
@ -215,22 +208,31 @@ ENTRY(cpu_throw)
|
||||
#else
|
||||
mcr p15, 0, r6, c13, c0, 3
|
||||
#endif
|
||||
|
||||
add sp, sp, #4;
|
||||
ldmfd sp!, {r4-r7, pc}
|
||||
/* Restore all the saved registers and exit */
|
||||
add r3, r7, #PCB_R4
|
||||
ldmia r3, {r4-r12, sp, pc}
|
||||
END(cpu_throw)
|
||||
|
||||
/*
|
||||
* cpu_switch(oldtd, newtd, lock)
|
||||
*
|
||||
* Save the current thread state, then select the next thread to run
|
||||
* and load its state.
|
||||
* r0 = oldtd
|
||||
* r1 = newtd
|
||||
* r2 = lock (new lock for old thread)
|
||||
*/
|
||||
ENTRY(cpu_switch)
|
||||
stmfd sp!, {r4-r7, lr}
|
||||
sub sp, sp, #4;
|
||||
#ifdef __ARM_EABI__
|
||||
.save {r4-r7, lr}
|
||||
.pad #4
|
||||
#endif
|
||||
/* Interrupts are disabled. */
|
||||
/* Save all the registers in the old thread's pcb. */
|
||||
ldr r3, [r0, #(TD_PCB)]
|
||||
|
||||
/* Restore all the saved registers and exit */
|
||||
add r3, #(PCB_R4)
|
||||
stmia r3, {r4-r12, sp, lr, pc}
|
||||
|
||||
mov r6, r2 /* Save the mutex */
|
||||
|
||||
.Lswitch_resume:
|
||||
/* rem: r0 = old lwp */
|
||||
/* rem: interrupts are disabled */
|
||||
|
||||
@ -246,30 +248,12 @@ ENTRY(cpu_switch)
|
||||
ldr r2, [r1, #TD_PCB]
|
||||
str r2, [r7, #PC_CURPCB]
|
||||
|
||||
/* rem: r1 = new process */
|
||||
/* rem: interrupts are enabled */
|
||||
|
||||
/* Stage two : Save old context */
|
||||
|
||||
/* Get the user structure for the old thread. */
|
||||
ldr r2, [r0, #(TD_PCB)]
|
||||
mov r4, r0 /* Save the old thread. */
|
||||
|
||||
/* Save all the registers in the old thread's pcb */
|
||||
#ifndef _ARM_ARCH_5E
|
||||
add r7, r2, #(PCB_R8)
|
||||
stmia r7, {r8-r13}
|
||||
#else
|
||||
strd r8, [r2, #(PCB_R8)]
|
||||
strd r10, [r2, #(PCB_R10)]
|
||||
strd r12, [r2, #(PCB_R12)]
|
||||
#endif
|
||||
str pc, [r2, #(PCB_PC)]
|
||||
|
||||
/*
|
||||
* NOTE: We can now use r8-r13 until it is time to restore
|
||||
* them for the new process.
|
||||
*/
|
||||
#ifdef ARM_TP_ADDRESS
|
||||
/* Store the old tp */
|
||||
ldr r3, =ARM_TP_ADDRESS
|
||||
@ -318,7 +302,6 @@ ENTRY(cpu_switch)
|
||||
|
||||
/* rem: r2 = old PCB */
|
||||
/* rem: r9 = new PCB */
|
||||
/* rem: interrupts are enabled */
|
||||
|
||||
ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */
|
||||
mov r2, #DOMAIN_CLIENT
|
||||
@ -336,7 +319,6 @@ ENTRY(cpu_switch)
|
||||
mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */
|
||||
ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */
|
||||
|
||||
|
||||
teq r10, r11 /* Same L1? */
|
||||
cmpeq r0, r5 /* Same DACR? */
|
||||
beq .Lcs_context_switched /* yes! */
|
||||
@ -426,54 +408,18 @@ ENTRY(cpu_switch)
|
||||
|
||||
/* rem: r9 = new PCB */
|
||||
|
||||
/* Restore all the save registers */
|
||||
#ifndef _ARM_ARCH_5E
|
||||
add r7, r9, #PCB_R8
|
||||
ldmia r7, {r8-r13}
|
||||
sub r7, r7, #PCB_R8 /* restore PCB pointer */
|
||||
#else
|
||||
mov r7, r9
|
||||
ldr r8, [r7, #(PCB_R8)]
|
||||
ldr r9, [r7, #(PCB_R9)]
|
||||
ldr r10, [r7, #(PCB_R10)]
|
||||
ldr r11, [r7, #(PCB_R11)]
|
||||
ldr r12, [r7, #(PCB_R12)]
|
||||
ldr r13, [r7, #(PCB_SP)]
|
||||
#endif
|
||||
|
||||
/* rem: r5 = new lwp's proc */
|
||||
/* rem: r6 = lock */
|
||||
/* rem: r7 = new PCB */
|
||||
|
||||
.Lswitch_return:
|
||||
|
||||
/*
|
||||
* Pull the registers that got pushed when either savectx() or
|
||||
* cpu_switch() was called and return.
|
||||
*/
|
||||
add sp, sp, #4;
|
||||
ldmfd sp!, {r4-r7, pc}
|
||||
#ifdef DIAGNOSTIC
|
||||
.Lswitch_bogons:
|
||||
adr r0, .Lswitch_panic_str
|
||||
bl _C_LABEL(panic)
|
||||
1: nop
|
||||
b 1b
|
||||
|
||||
.Lswitch_panic_str:
|
||||
.asciz "cpu_switch: sched_qs empty with non-zero sched_whichqs!\n"
|
||||
#endif
|
||||
/* Restore all the saved registers and exit */
|
||||
add r3, r9, #PCB_R4
|
||||
ldmia r3, {r4-r12, sp, pc}
|
||||
END(cpu_switch)
|
||||
|
||||
ENTRY(savectx)
|
||||
stmfd sp!, {r4-r7, lr}
|
||||
stmfd sp!, {lr}
|
||||
sub sp, sp, #4
|
||||
/*
|
||||
* r0 = pcb
|
||||
*/
|
||||
/* Store all the registers in the process's pcb */
|
||||
add r2, r0, #(PCB_R8)
|
||||
stmia r2, {r8-r13}
|
||||
|
||||
/* Store all the registers in the thread's pcb */
|
||||
add r3, r0, #(PCB_R4)
|
||||
stmia r3, {r4-r12, sp, lr, pc}
|
||||
#ifdef VFP
|
||||
fmrx r2, fpexc /* If the VFP is enabled */
|
||||
tst r2, #(VFPEXC_EN) /* the current thread has */
|
||||
@ -482,7 +428,7 @@ ENTRY(savectx)
|
||||
blne _C_LABEL(vfp_store) /* and disable the VFP. */
|
||||
#endif
|
||||
add sp, sp, #4;
|
||||
ldmfd sp!, {r4-r7, pc}
|
||||
ldmfd sp!, {pc}
|
||||
END(savectx)
|
||||
|
||||
ENTRY(fork_trampoline)
|
||||
|
@ -545,7 +545,7 @@ dab_buserr(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
|
||||
* If the current trapframe is at the top of the kernel stack,
|
||||
* the fault _must_ have come from user mode.
|
||||
*/
|
||||
if (tf != ((struct trapframe *)pcb->un_32.pcb32_sp) - 1) {
|
||||
if (tf != ((struct trapframe *)pcb->pcb_regs.sf_sp) - 1) {
|
||||
/*
|
||||
* Kernel mode. We're either about to die a
|
||||
* spectacular death, or pcb_onfault will come
|
||||
|
@ -79,7 +79,7 @@ __FBSDID("$FreeBSD$");
|
||||
* struct switchframe and trapframe must both be a multiple of 8
|
||||
* for correct stack alignment.
|
||||
*/
|
||||
CTASSERT(sizeof(struct switchframe) == 24);
|
||||
CTASSERT(sizeof(struct switchframe) == 48);
|
||||
CTASSERT(sizeof(struct trapframe) == 80);
|
||||
|
||||
/*
|
||||
@ -93,43 +93,55 @@ cpu_fork(register struct thread *td1, register struct proc *p2,
|
||||
{
|
||||
struct pcb *pcb2;
|
||||
struct trapframe *tf;
|
||||
struct switchframe *sf;
|
||||
struct mdproc *mdp2;
|
||||
|
||||
if ((flags & RFPROC) == 0)
|
||||
return;
|
||||
pcb2 = (struct pcb *)(td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1;
|
||||
|
||||
/* Point the pcb to the top of the stack */
|
||||
pcb2 = (struct pcb *)
|
||||
(td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1;
|
||||
#ifdef __XSCALE__
|
||||
#ifndef CPU_XSCALE_CORE3
|
||||
pmap_use_minicache(td2->td_kstack, td2->td_kstack_pages * PAGE_SIZE);
|
||||
#endif
|
||||
#endif
|
||||
td2->td_pcb = pcb2;
|
||||
|
||||
/* Clone td1's pcb */
|
||||
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
|
||||
|
||||
/* Point to mdproc and then copy over td1's contents */
|
||||
mdp2 = &p2->p_md;
|
||||
bcopy(&td1->td_proc->p_md, mdp2, sizeof(*mdp2));
|
||||
pcb2->un_32.pcb32_sp = td2->td_kstack +
|
||||
USPACE_SVC_STACK_TOP - sizeof(*pcb2);
|
||||
|
||||
/* Point the frame to the stack in front of pcb and copy td1's frame */
|
||||
td2->td_frame = (struct trapframe *)pcb2 - 1;
|
||||
*td2->td_frame = *td1->td_frame;
|
||||
|
||||
/*
|
||||
* Create a new 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.
|
||||
*/
|
||||
pmap_set_pcb_pagedir(vmspace_pmap(p2->p_vmspace), pcb2);
|
||||
pcb2->pcb_regs.sf_r4 = (register_t)fork_return;
|
||||
pcb2->pcb_regs.sf_r5 = (register_t)td2;
|
||||
pcb2->pcb_regs.sf_lr = (register_t)fork_trampoline;
|
||||
pcb2->pcb_regs.sf_sp = STACKALIGN(td2->td_frame);
|
||||
|
||||
pcb2->pcb_vfpcpu = -1;
|
||||
pcb2->pcb_vfpstate.fpscr = VFPSCR_DN | VFPSCR_FZ;
|
||||
pmap_activate(td2);
|
||||
td2->td_frame = tf = (struct trapframe *)STACKALIGN(
|
||||
pcb2->un_32.pcb32_sp - sizeof(struct trapframe));
|
||||
*tf = *td1->td_frame;
|
||||
sf = (struct switchframe *)tf - 1;
|
||||
sf->sf_r4 = (u_int)fork_return;
|
||||
sf->sf_r5 = (u_int)td2;
|
||||
sf->sf_pc = (u_int)fork_trampoline;
|
||||
|
||||
tf = td2->td_frame;
|
||||
tf->tf_spsr &= ~PSR_C;
|
||||
tf->tf_r0 = 0;
|
||||
tf->tf_r1 = 0;
|
||||
pcb2->un_32.pcb32_sp = (u_int)sf;
|
||||
KASSERT((pcb2->un_32.pcb32_sp & 7) == 0,
|
||||
("cpu_fork: Incorrect stack alignment"));
|
||||
|
||||
|
||||
/* Setup to release spin count in fork_exit(). */
|
||||
td2->td_md.md_spinlock_count = 1;
|
||||
td2->td_md.md_saved_cspr = 0;
|
||||
td2->td_md.md_saved_cspr = PSR_SVC32_MODE;;
|
||||
#ifdef ARM_TP_ADDRESS
|
||||
td2->td_md.md_tp = *(register_t *)ARM_TP_ADDRESS;
|
||||
#else
|
||||
@ -218,25 +230,21 @@ cpu_set_syscall_retval(struct thread *td, int error)
|
||||
void
|
||||
cpu_set_upcall(struct thread *td, struct thread *td0)
|
||||
{
|
||||
struct trapframe *tf;
|
||||
struct switchframe *sf;
|
||||
|
||||
bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
|
||||
bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb));
|
||||
tf = td->td_frame;
|
||||
sf = (struct switchframe *)tf - 1;
|
||||
sf->sf_r4 = (u_int)fork_return;
|
||||
sf->sf_r5 = (u_int)td;
|
||||
sf->sf_pc = (u_int)fork_trampoline;
|
||||
tf->tf_spsr &= ~PSR_C;
|
||||
tf->tf_r0 = 0;
|
||||
td->td_pcb->un_32.pcb32_sp = (u_int)sf;
|
||||
KASSERT((td->td_pcb->un_32.pcb32_sp & 7) == 0,
|
||||
("cpu_set_upcall: Incorrect stack alignment"));
|
||||
|
||||
td->td_pcb->pcb_regs.sf_r4 = (register_t)fork_return;
|
||||
td->td_pcb->pcb_regs.sf_r5 = (register_t)td;
|
||||
td->td_pcb->pcb_regs.sf_lr = (register_t)fork_trampoline;
|
||||
td->td_pcb->pcb_regs.sf_sp = STACKALIGN(td->td_frame);
|
||||
|
||||
td->td_frame->tf_spsr &= ~PSR_C;
|
||||
td->td_frame->tf_r0 = 0;
|
||||
|
||||
/* Setup to release spin count in fork_exit(). */
|
||||
td->td_md.md_spinlock_count = 1;
|
||||
td->td_md.md_saved_cspr = 0;
|
||||
td->td_md.md_saved_cspr = PSR_SVC32_MODE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -250,8 +258,7 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
|
||||
{
|
||||
struct trapframe *tf = td->td_frame;
|
||||
|
||||
tf->tf_usr_sp = STACKALIGN((int)stack->ss_sp + stack->ss_size
|
||||
- sizeof(struct trapframe));
|
||||
tf->tf_usr_sp = STACKALIGN((int)stack->ss_sp + stack->ss_size);
|
||||
tf->tf_pc = (int)entry;
|
||||
tf->tf_r0 = (int)arg;
|
||||
tf->tf_spsr = PSR_USR32_MODE;
|
||||
@ -289,9 +296,8 @@ cpu_thread_alloc(struct thread *td)
|
||||
* placed into the stack pointer which must be 8 byte aligned in
|
||||
* the ARM EABI.
|
||||
*/
|
||||
td->td_frame = (struct trapframe *)STACKALIGN((u_int)td->td_kstack +
|
||||
USPACE_SVC_STACK_TOP - sizeof(struct pcb) -
|
||||
sizeof(struct trapframe));
|
||||
td->td_frame = (struct trapframe *)((caddr_t)td->td_pcb) - 1;
|
||||
|
||||
#ifdef __XSCALE__
|
||||
#ifndef CPU_XSCALE_CORE3
|
||||
pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE);
|
||||
@ -318,16 +324,8 @@ cpu_thread_clean(struct thread *td)
|
||||
void
|
||||
cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg)
|
||||
{
|
||||
struct switchframe *sf;
|
||||
struct trapframe *tf;
|
||||
|
||||
tf = td->td_frame;
|
||||
sf = (struct switchframe *)tf - 1;
|
||||
sf->sf_r4 = (u_int)func;
|
||||
sf->sf_r5 = (u_int)arg;
|
||||
td->td_pcb->un_32.pcb32_sp = (u_int)sf;
|
||||
KASSERT((td->td_pcb->un_32.pcb32_sp & 7) == 0,
|
||||
("cpu_set_fork_handler: Incorrect stack alignment"));
|
||||
td->td_pcb->pcb_regs.sf_r4 = (register_t)func; /* function */
|
||||
td->td_pcb->pcb_regs.sf_r5 = (register_t)arg; /* first arg */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -38,7 +38,7 @@
|
||||
typedef vm_offset_t db_addr_t;
|
||||
typedef int db_expr_t;
|
||||
|
||||
#define PC_REGS() ((db_addr_t)kdb_thrctx->un_32.pcb32_pc)
|
||||
#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_regs.sf_pc)
|
||||
|
||||
#define BKPT_INST (KERNEL_BREAKPOINT)
|
||||
#define BKPT_SIZE (INSN_SIZE)
|
||||
|
@ -86,57 +86,16 @@ struct trapframe {
|
||||
#define tf_r13 tf_usr_sp
|
||||
#define tf_r14 tf_usr_lr
|
||||
#define tf_r15 tf_pc
|
||||
/*
|
||||
* * Scheduler activations upcall frame. Pushed onto user stack before
|
||||
* * calling an SA upcall.
|
||||
* */
|
||||
|
||||
struct saframe {
|
||||
#if 0 /* in registers on entry to upcall */
|
||||
int sa_type;
|
||||
struct sa_t ** sa_sas;
|
||||
int sa_events;
|
||||
int sa_interrupted;
|
||||
#endif
|
||||
void * sa_arg;
|
||||
};
|
||||
|
||||
/*
|
||||
* * Signal frame. Pushed onto user stack before calling sigcode.
|
||||
* */
|
||||
|
||||
/* the pointers are use in the trampoline code to locate the ucontext */
|
||||
* Signal frame. Pushed onto user stack before calling sigcode.
|
||||
* The pointers are used in the trampoline code to locate the ucontext.
|
||||
*/
|
||||
struct sigframe {
|
||||
siginfo_t sf_si; /* actual saved siginfo */
|
||||
ucontext_t sf_uc; /* actual saved ucontext */
|
||||
};
|
||||
|
||||
/*
|
||||
* System stack frames.
|
||||
*/
|
||||
|
||||
|
||||
typedef struct irqframe {
|
||||
unsigned int if_spsr;
|
||||
unsigned int if_r0;
|
||||
unsigned int if_r1;
|
||||
unsigned int if_r2;
|
||||
unsigned int if_r3;
|
||||
unsigned int if_r4;
|
||||
unsigned int if_r5;
|
||||
unsigned int if_r6;
|
||||
unsigned int if_r7;
|
||||
unsigned int if_r8;
|
||||
unsigned int if_r9;
|
||||
unsigned int if_r10;
|
||||
unsigned int if_r11;
|
||||
unsigned int if_r12;
|
||||
unsigned int if_usr_sp;
|
||||
unsigned int if_usr_lr;
|
||||
unsigned int if_svc_sp;
|
||||
unsigned int if_svc_lr;
|
||||
unsigned int if_pc;
|
||||
} irqframe_t;
|
||||
|
||||
/*
|
||||
* Switch frame.
|
||||
@ -144,16 +103,23 @@ typedef struct irqframe {
|
||||
* It is important this is a multiple of 8 bytes so the stack is correctly
|
||||
* aligned when we create new threads.
|
||||
*/
|
||||
|
||||
struct switchframe {
|
||||
u_int pad; /* Used to pad the struct to a multiple of 8-bytes */
|
||||
u_int sf_r4;
|
||||
u_int sf_r5;
|
||||
u_int sf_r6;
|
||||
u_int sf_r7;
|
||||
u_int sf_pc;
|
||||
struct switchframe
|
||||
{
|
||||
register_t sf_r4;
|
||||
register_t sf_r5;
|
||||
register_t sf_r6;
|
||||
register_t sf_r7;
|
||||
register_t sf_r8;
|
||||
register_t sf_r9;
|
||||
register_t sf_r10;
|
||||
register_t sf_r11;
|
||||
register_t sf_r12;
|
||||
register_t sf_sp;
|
||||
register_t sf_lr;
|
||||
register_t sf_pc;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Stack frame. Used during stack traces (db_trace.c)
|
||||
*/
|
||||
|
@ -39,50 +39,29 @@
|
||||
#define _MACHINE_PCB_H_
|
||||
|
||||
#include <machine/fp.h>
|
||||
#include <machine/frame.h>
|
||||
|
||||
|
||||
struct trapframe;
|
||||
|
||||
struct pcb_arm32 {
|
||||
vm_offset_t pcb32_pagedir; /* PT hooks */
|
||||
uint32_t *pcb32_pl1vec; /* PTR to vector_base L1 entry*/
|
||||
uint32_t pcb32_l1vec; /* Value to stuff on ctx sw */
|
||||
u_int pcb32_dacr; /* Domain Access Control Reg */
|
||||
/*
|
||||
* WARNING!
|
||||
* cpuswitch.S relies on pcb32_r8 being quad-aligned in struct pcb
|
||||
* (due to the use of "strd" when compiled for XSCALE)
|
||||
*/
|
||||
u_int pcb32_r8; /* used */
|
||||
u_int pcb32_r9; /* used */
|
||||
u_int pcb32_r10; /* used */
|
||||
u_int pcb32_r11; /* used */
|
||||
u_int pcb32_r12; /* used */
|
||||
u_int pcb32_sp; /* used */
|
||||
u_int pcb32_lr;
|
||||
u_int pcb32_pc;
|
||||
};
|
||||
#define pcb_pagedir un_32.pcb32_pagedir
|
||||
#define pcb_pl1vec un_32.pcb32_pl1vec
|
||||
#define pcb_l1vec un_32.pcb32_l1vec
|
||||
#define pcb_dacr un_32.pcb32_dacr
|
||||
#define pcb_cstate un_32.pcb32_cstate
|
||||
|
||||
/*
|
||||
* WARNING!
|
||||
* See warning for struct pcb_arm32, above, before changing struct pcb!
|
||||
* Keep pcb_regs first for faster access in switch.S
|
||||
*/
|
||||
struct pcb {
|
||||
struct switchframe pcb_regs; /* CPU state */
|
||||
u_int pcb_flags;
|
||||
#define PCB_OWNFPU 0x00000001
|
||||
#define PCB_NOALIGNFLT 0x00000002
|
||||
caddr_t pcb_onfault; /* On fault handler */
|
||||
struct pcb_arm32 un_32;
|
||||
vm_offset_t pcb_pagedir; /* PT hooks */
|
||||
uint32_t *pcb_pl1vec; /* PTR to vector_base L1 entry*/
|
||||
uint32_t pcb_l1vec; /* Value to stuff on ctx sw */
|
||||
u_int pcb_dacr; /* Domain Access Control Reg */
|
||||
|
||||
struct vfp_state pcb_vfpstate; /* VP/NEON state */
|
||||
u_int pcb_vfpcpu; /* VP/NEON last cpu */
|
||||
} __aligned(8); /*
|
||||
* We need the PCB to be aligned on 8 bytes, as we may
|
||||
* access it using ldrd/strd, and some CPUs require it
|
||||
* access it using ldrd/strd, and ARM ABI require it
|
||||
* to by aligned on 8 bytes.
|
||||
*/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user