Skip to content

Commit 276f500

Browse files
committed
Remove mc_pc entirely from the purecap mcontext_t.
Instead, purecap is expected to always manipulate mc_cheriframe.cf_pcc directly. freebsd64_setmcontext() now takes care of applying the 64-bit mc_pc as an offset to pcc and freebsd64_getmcontext() stores the offset of pcc in mc_pc. get/set_mcontext() in a CHERI kernel (hybrid and purecap) only operate on pcc. This did entail fixing some some code in the CHERI C tests. Some of it is still dubious (specifically how CJR/CJALR are handled for the hybrid case), but I suspect hybrid just never uses those instructions.
1 parent 456b5fe commit 276f500

File tree

5 files changed

+47
-26
lines changed

5 files changed

+47
-26
lines changed

contrib/subrepo-cheri-c-tests/test_runtime.c

+33-19
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ enum cheri_branch_ops
115115
static inline struct cheri_frame *
116116
getCHERIFrame(mcontext_t *context)
117117
{
118-
#ifdef __CHERI_SANDBOX__
118+
#ifdef __CHERI_PURE_CAPABILITY__
119119
return &context->mc_cheriframe;
120120
#else
121121
assert_eq(context->mc_cp2state_len, sizeof(struct cheri_frame));
@@ -239,6 +239,18 @@ isInDelaySlot(mcontext_t *context)
239239
return getImm(context->cause, 31, 1);
240240
}
241241

242+
static inline void
243+
setPc(mcontext_t *context, register_t pc)
244+
{
245+
#ifdef __CHERI_PURE_CAPABILITY__
246+
struct cheri_frame *frame = getCHERIFrame(context);
247+
248+
frame->cf_pcc = __builtin_cheri_offset_set(frame->cf_pcc, pc);
249+
#else
250+
context->mc_pc = pc;
251+
#endif
252+
}
253+
242254
/**
243255
* If we are in a branch delay slot, work out what the next instruction will
244256
* be. This is either the branch target or the instruction immediately
@@ -279,42 +291,42 @@ emulateBranch(mcontext_t *context, register_t pc)
279291
"In delay slot for not-taken likely branch!");
280292
case MIPS_BRANCH_BLTZ:
281293
case MIPS_BRANCH_BLTZAL:
282-
context->mc_pc = ((regVal < 0) ? branchPc : normalPc);
294+
setPc(context, (regVal < 0) ? branchPc : normalPc);
283295
return true;
284296
case MIPS_BRANCH_BGEZL:
285297
case MIPS_BRANCH_BGEZ:
286298
assert((regVal < 0) &&
287299
"In delay slot for not-taken likely branch!");
288300
case MIPS_BRANCH_BGEZAL:
289301
case MIPS_BRANCH_BGEZALL:
290-
context->mc_pc = ((regVal >= 0) ? branchPc : normalPc);
302+
setPc(context, (regVal >= 0) ? branchPc : normalPc);
291303
return true;
292304
}
293305
break;
294306
}
295307
case MIPS_BRANCH_J:
296308
case MIPS_BRANCH_JAL:
297-
context->mc_pc = (getImm(instr, 25, 0)<<2) & ((pc >> 28) << 28);
309+
setPc(context, (getImm(instr, 25, 0)<<2) & ((pc >> 28) << 28));
298310
return true;
299311
case MIPS_BRANCH_JR:
300312
case MIPS_BRANCH_JALR:
301-
context->mc_pc = getReg(context, instr, 25);
313+
setPc(context, getReg(context, instr, 25));
302314
return true;
303315
case MIPS_BRANCH_BEQL:
304316
case MIPS_BRANCH_BEQ:
305-
context->mc_pc = ((regVal == regVal2) ? branchPc : normalPc);
317+
setPc(context, (regVal == regVal2) ? branchPc : normalPc);
306318
return true;
307319
case MIPS_BRANCH_BNEL:
308320
case MIPS_BRANCH_BNE:
309-
context->mc_pc = ((regVal != regVal2) ? branchPc : normalPc);
321+
setPc(context, (regVal != regVal2) ? branchPc : normalPc);
310322
return true;
311323
case MIPS_BRANCH_BLEZL:
312324
case MIPS_BRANCH_BLEZ:
313-
context->mc_pc = ((regVal <= 0) ? branchPc : normalPc);
325+
setPc(context, (regVal <= 0) ? branchPc : normalPc);
314326
return true;
315327
case MIPS_BRANCH_BGTZL:
316328
case MIPS_BRANCH_BGTZ:
317-
context->mc_pc = ((regVal > 0) ? branchPc : normalPc);
329+
setPc(context, (regVal > 0) ? branchPc : normalPc);
318330
return true;
319331
case MIPS_BRANCH_CHERI:
320332
{
@@ -324,28 +336,26 @@ emulateBranch(mcontext_t *context, register_t pc)
324336
{
325337
void * __capability cap = getCapReg(context, instr, 20);
326338
bool tag = __builtin_cheri_tag_get(cap);
327-
context->mc_pc = (!tag ? branchPc : normalPc);
339+
setPc(context, !tag ? branchPc : normalPc);
328340
return true;
329341
}
330342
case CHERI_BRANCH_CBTS:
331343
{
332344
void * __capability cap = getCapReg(context, instr, 20);
333345
bool tag = __builtin_cheri_tag_get(cap);
334-
context->mc_pc = (tag ? branchPc : normalPc);
346+
setPc(context, tag ? branchPc : normalPc);
335347
return true;
336348
}
337349
case CHERI_BRANCH_CJR:
338350
case CHERI_BRANCH_CJALR:
339351
{
340-
context->mc_pc = getReg(context, instr, 10);
341352
// FIXME: This is very ugly, but to fix it we need to
342353
// define a new structure to replace cheri_frame.
343354
struct cheri_frame *frame = getCHERIFrame(context);
344-
// Note: The /cap_size is safe here because if this is not
345-
// aligned then the load will fail anyway...
346-
int regno = offsetof(struct cheri_frame, cf_pcc) / cap_size;
347-
(((void * __capability*)frame)[regno]) =
348-
getCapReg(context, instr, 15);
355+
frame->cf_pcc = getCapReg(context, instr, 15);
356+
#ifndef __CHERI_PURE_CAPABILITY__
357+
context->mc_pc = __builtin_cheri_offset_get(frame->cf_pcc);
358+
#endif
349359
return true;
350360
}
351361
}
@@ -363,8 +373,12 @@ capsighandler(int signo, siginfo_t *info __unused, ucontext_t *uap)
363373
{
364374
mcontext_t *context = &uap->uc_mcontext;
365375
bool isDelaySlot = isInDelaySlot(context);
366-
register_t pc = context->mc_pc;
367376
struct cheri_frame *frame = getCHERIFrame(context);
377+
#ifdef __CHERI_PURE_CAPABILITY__
378+
register_t pc = __builtin_cheri_offset_get(frame->cf_pcc);
379+
#else
380+
register_t pc = context->mc_pc;
381+
#endif
368382
void * __capability reg = getCapRegAtIndex(context, frame->cf_capcause & 0xff);
369383
assert_eq(signo, SIGPROT);
370384
assert(test_fault_handler);
@@ -386,7 +400,7 @@ capsighandler(int signo, siginfo_t *info __unused, ucontext_t *uap)
386400
}
387401
else
388402
{
389-
context->mc_pc += 4;
403+
setPc(context, pc + 4);
390404
}
391405
}
392406

lib/libc/mips/gen/makecontext.c

-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
9898
mc->mc_cheriframe.cf_c16 = ucp;
9999
mc->mc_cheriframe.cf_c12 = func;
100100
mc->mc_cheriframe.cf_pcc = _ctx_start;
101-
mc->mc_pc = (__cheri_offset register_t)mc->mc_cheriframe.cf_pcc;
102101
#else
103102
mc->mc_regs[SP] = (intptr_t)sp;
104103
mc->mc_regs[S0] = (intptr_t)ucp;

sys/mips/include/ucontext.h

+5
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ typedef struct __mcontext {
5353
* struct sigcontext and ucontext_t at the same time.
5454
*/
5555
int mc_onstack; /* sigstack state to restore */
56+
#if (defined(_KERNEL) && __has_feature(capabilities)) || \
57+
defined(__CHERI_PURE_CAPABILITY__)
58+
__register_t __unused_pc; /* purecap only uses pcc */
59+
#else
5660
__register_t mc_pc; /* pc at time of signal */
61+
#endif
5762
__register_t mc_regs[32]; /* processor regs 0 to 31 */
5863
__register_t sr; /* status register */
5964
__register_t mullo, mulhi; /* mullo and mulhi registers... */

sys/mips/mips/freebsd64_machdep.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#include <cheri/cheric.h>
6969

7070
#include <machine/abi.h>
71+
#include <machine/cheri_machdep.h>
7172
#include <machine/cpuinfo.h>
7273
#include <machine/md_var.h>
7374
#include <machine/pcb.h>
@@ -191,7 +192,7 @@ freebsd64_get_mcontext(struct thread *td, mcontext64_t *mcp, int flags)
191192
return (error);
192193

193194
mcp->mc_onstack = mc.mc_onstack;
194-
mcp->mc_pc = mc.mc_pc;
195+
mcp->mc_pc = cheri_getoffset(mc.mc_cheriframe.cf_pcc);
195196
for (i = 0; i < 32; i++)
196197
mcp->mc_regs[i] = mc.mc_regs[i];
197198
mcp->sr = mc.sr;
@@ -247,7 +248,8 @@ freebsd64_set_mcontext(struct thread *td, mcontext64_t *mcp)
247248
}
248249

249250
mc.mc_onstack = mcp->mc_onstack;
250-
mc.mc_pc = mcp->mc_pc;
251+
mc.mc_cheriframe.cf_pcc = update_pcc_offset(mc.mc_cheriframe.cf_pcc,
252+
mcp->mc_pc);
251253
for (i = 0; i < 32; i++)
252254
mc.mc_regs[i] = mcp->mc_regs[i];
253255
mc.sr = mcp->sr;

sys/mips/mips/pm_machdep.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
189189
sf.sf_uc.uc_sigmask = *mask;
190190
sf.sf_uc.uc_stack = td->td_sigstk;
191191
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
192+
#if !__has_feature(capabilities)
192193
sf.sf_uc.uc_mcontext.mc_pc = TRAPF_PC_OFFSET(regs);
194+
#endif
193195
sf.sf_uc.uc_mcontext.mullo = regs->mullo;
194196
sf.sf_uc.uc_mcontext.mulhi = regs->mulhi;
195197
sf.sf_uc.uc_mcontext.mc_tls = td->td_md.md_tls;
@@ -540,7 +542,9 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
540542
#endif
541543
}
542544

545+
#if !__has_feature(capabilities)
543546
mcp->mc_pc = TRAPF_PC_OFFSET(td->td_frame);
547+
#endif
544548
mcp->mullo = td->td_frame->mullo;
545549
mcp->mulhi = td->td_frame->mulhi;
546550
mcp->mc_tls = td->td_md.md_tls;
@@ -569,10 +573,7 @@ set_mcontext(struct thread *td, mcontext_t *mcp)
569573
bcopy((void *)&mcp->mc_fpregs, (void *)&td->td_frame->f0,
570574
sizeof(mcp->mc_fpregs));
571575
}
572-
#if __has_feature(capabilities)
573-
td->td_frame->pc =
574-
update_pcc_offset(mcp->mc_cheriframe.cf_pcc, mcp->mc_pc);
575-
#else
576+
#if !__has_feature(capabilities)
576577
td->td_frame->pc = (trapf_pc_t) mcp->mc_pc;
577578
#endif
578579
td->td_frame->mullo = mcp->mullo;

0 commit comments

Comments
 (0)