Commit 39d4a447 authored by Stéphane Eranian's avatar Stéphane Eranian Committed by David Mosberger

[PATCH] ia64: perfmon update

Please apply the following patch on top of 2.5.6x. This patch does the
following:

- repair broken system-wide overflow notification
- repair broken per-process notification
- fix a problem in the resrved bitmask for opcode 
  matcher8,9 for McKinley as reported by UIUC.
- forcing of bit2 for pmc8/pmc9 now part of reserved bitmask
- add the unsecure option to perfmon
- update to perfmon 1.4 (similar to 2.4)
parent f76865d6
...@@ -225,8 +225,9 @@ typedef struct { ...@@ -225,8 +225,9 @@ typedef struct {
unsigned int protected:1; /* allow access to creator of context only */ unsigned int protected:1; /* allow access to creator of context only */
unsigned int using_dbreg:1; /* using range restrictions (debug registers) */ unsigned int using_dbreg:1; /* using range restrictions (debug registers) */
unsigned int excl_idle:1; /* exclude idle task in system wide session */ unsigned int excl_idle:1; /* exclude idle task in system wide session */
unsigned int unsecure:1; /* sp = 0 for non self-monitored task */
unsigned int trap_reason:2; /* reason for going into pfm_block_ovfl_reset() */ unsigned int trap_reason:2; /* reason for going into pfm_block_ovfl_reset() */
unsigned int reserved:21; unsigned int reserved:20;
} pfm_context_flags_t; } pfm_context_flags_t;
#define PFM_TRAP_REASON_NONE 0x0 /* default value */ #define PFM_TRAP_REASON_NONE 0x0 /* default value */
...@@ -279,6 +280,7 @@ typedef struct pfm_context { ...@@ -279,6 +280,7 @@ typedef struct pfm_context {
#define ctx_fl_using_dbreg ctx_flags.using_dbreg #define ctx_fl_using_dbreg ctx_flags.using_dbreg
#define ctx_fl_excl_idle ctx_flags.excl_idle #define ctx_fl_excl_idle ctx_flags.excl_idle
#define ctx_fl_trap_reason ctx_flags.trap_reason #define ctx_fl_trap_reason ctx_flags.trap_reason
#define ctx_fl_unsecure ctx_flags.unsecure
/* /*
* global information about all sessions * global information about all sessions
...@@ -1077,10 +1079,15 @@ pfx_is_sane(struct task_struct *task, pfarg_context_t *pfx) ...@@ -1077,10 +1079,15 @@ pfx_is_sane(struct task_struct *task, pfarg_context_t *pfx)
* and it must be a valid CPU * and it must be a valid CPU
*/ */
cpu = ffz(~pfx->ctx_cpu_mask); cpu = ffz(~pfx->ctx_cpu_mask);
#ifdef CONFIG_SMP
if (cpu_online(cpu) == 0) { if (cpu_online(cpu) == 0) {
#else
if (cpu != 0) {
#endif
DBprintk(("CPU%d is not online\n", cpu)); DBprintk(("CPU%d is not online\n", cpu));
return -EINVAL; return -EINVAL;
} }
/* /*
* check for pre-existing pinning, if conflicting reject * check for pre-existing pinning, if conflicting reject
*/ */
...@@ -1226,6 +1233,7 @@ pfm_context_create(struct task_struct *task, pfm_context_t *ctx, void *req, int ...@@ -1226,6 +1233,7 @@ pfm_context_create(struct task_struct *task, pfm_context_t *ctx, void *req, int
ctx->ctx_fl_block = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0; ctx->ctx_fl_block = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0;
ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0;
ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0; ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0;
ctx->ctx_fl_unsecure = (ctx_flags & PFM_FL_UNSECURE) ? 1: 0;
ctx->ctx_fl_frozen = 0; ctx->ctx_fl_frozen = 0;
ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
...@@ -1252,9 +1260,11 @@ pfm_context_create(struct task_struct *task, pfm_context_t *ctx, void *req, int ...@@ -1252,9 +1260,11 @@ pfm_context_create(struct task_struct *task, pfm_context_t *ctx, void *req, int
DBprintk(("context=%p, pid=%d notify_task=%p\n", DBprintk(("context=%p, pid=%d notify_task=%p\n",
(void *)ctx, task->pid, ctx->ctx_notify_task)); (void *)ctx, task->pid, ctx->ctx_notify_task));
DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d\n", DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d unsecure=%d\n",
(void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit, (void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit,
ctx->ctx_fl_block, ctx->ctx_fl_system, ctx->ctx_fl_excl_idle)); ctx->ctx_fl_block, ctx->ctx_fl_system,
ctx->ctx_fl_excl_idle,
ctx->ctx_fl_unsecure));
/* /*
* when no notification is required, we can make this visible at the last moment * when no notification is required, we can make this visible at the last moment
...@@ -1883,7 +1893,10 @@ pfm_restart(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, ...@@ -1883,7 +1893,10 @@ pfm_restart(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
DBprintk(("unblocking %d \n", task->pid)); DBprintk(("unblocking %d \n", task->pid));
up(sem); up(sem);
} else { } else {
struct thread_info *info = (struct thread_info *) ((char *) task + IA64_TASK_SIZE);
task->thread.pfm_ovfl_block_reset = 1; task->thread.pfm_ovfl_block_reset = 1;
ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_RESET;
set_bit(TIF_NOTIFY_RESUME, &info->flags);
} }
#if 0 #if 0
/* /*
...@@ -2052,7 +2065,7 @@ pfm_protect_context(struct task_struct *task, pfm_context_t *ctx, void *arg, int ...@@ -2052,7 +2065,7 @@ pfm_protect_context(struct task_struct *task, pfm_context_t *ctx, void *arg, int
/* /*
* reinforce secure monitoring: cannot toggle psr.up * reinforce secure monitoring: cannot toggle psr.up
*/ */
ia64_psr(regs)->sp = 1; if (ctx->ctx_fl_unsecure == 0) ia64_psr(regs)->sp = 1;
return 0; return 0;
} }
...@@ -2733,12 +2746,13 @@ pfm_ovfl_block_reset(void) ...@@ -2733,12 +2746,13 @@ pfm_ovfl_block_reset(void)
* again * again
*/ */
th->pfm_ovfl_block_reset = 0; th->pfm_ovfl_block_reset = 0;
clear_thread_flag(TIF_NOTIFY_RESUME);
/* /*
* do some sanity checks first * do some sanity checks first
*/ */
if (!ctx) { if (!ctx) {
printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid); printk(KERN_ERR "perfmon: [%d] has no PFM context\n", current->pid);
return; return;
} }
/* /*
...@@ -2901,14 +2915,17 @@ pfm_record_sample(struct task_struct *task, pfm_context_t *ctx, unsigned long ov ...@@ -2901,14 +2915,17 @@ pfm_record_sample(struct task_struct *task, pfm_context_t *ctx, unsigned long ov
/* /*
* main overflow processing routine. * main overflow processing routine.
* it can be called from the interrupt path or explicitely during the context switch code * it can be called from the interrupt path or explicitely during the context switch code
* Arguments:
* mode: 0=coming from PMU interrupt, 1=coming from ctxsw
*
* Return: * Return:
* new value of pmc[0]. if 0x0 then unfreeze, else keep frozen * new value of pmc[0]. if 0x0 then unfreeze, else keep frozen
*/ */
static unsigned long static unsigned long
pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs) pfm_overflow_handler(int mode, struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs)
{ {
unsigned long mask;
struct thread_struct *t; struct thread_struct *t;
unsigned long mask;
unsigned long old_val; unsigned long old_val;
unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL; unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL;
int i; int i;
...@@ -2999,10 +3016,10 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str ...@@ -2999,10 +3016,10 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
/* /*
* check for sampling buffer * check for sampling buffer
* *
* if present, record sample. We propagate notification ONLY when buffer * if present, record sample only when a 64-bit counter has overflowed.
* becomes full. * We propagate notification ONLY when buffer becomes full.
*/ */
if(CTX_HAS_SMPL(ctx)) { if(CTX_HAS_SMPL(ctx) && ovfl_pmds) {
ret = pfm_record_sample(task, ctx, ovfl_pmds, regs); ret = pfm_record_sample(task, ctx, ovfl_pmds, regs);
if (ret == 1) { if (ret == 1) {
/* /*
...@@ -3047,12 +3064,55 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str ...@@ -3047,12 +3064,55 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
* ctx_notify_task could already be NULL, checked in pfm_notify_user() * ctx_notify_task could already be NULL, checked in pfm_notify_user()
*/ */
if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) { if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) {
t->pfm_ovfl_block_reset = 1; /* will cause blocking */
ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG; ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG;
} else { } else {
t->pfm_ovfl_block_reset = 1; /* will cause blocking */
ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG; ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG;
} }
/*
* we cannot block in system wide mode and we do not go
* through the PMU ctxsw code. Therefore we can generate
* the notification here. In system wide mode, the current
* task maybe different from the task controlling the session
* on this CPU, therefore owner can be different from current.
*
* In per-process mode, this function gets called from
* the interrupt handler or pfm_load_regs(). The mode argument
* tells where we are coming from. When coming from the interrupt
* handler, it is safe to notify (send signal) right here because
* we do not hold any runqueue locks needed by send_sig_info().
*
* However when coming from ctxsw, we cannot send the signal here.
* It must be deferred until we are sure we do not hold any runqueue
* related locks. The current task maybe different from the owner
* only in UP mode. The deferral is implemented using the
* TIF_NOTIFY_RESUME mechanism. In this case, the pending work
* is checked when the task is about to leave the kernel (see
* entry.S). As of this version of perfmon, a kernel only
* task cannot be monitored in per-process mode. Therefore,
* when this function gets called from pfm_load_regs(), we know
* we have a user level task which will eventually either exit
* or leave the kernel, and thereby go through the checkpoint
* for TIF_*.
*/
if (ctx->ctx_fl_system || mode == 0) {
pfm_notify_user(ctx);
ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
} else {
struct thread_info *info;
/*
* given that TIF_NOTIFY_RESUME is not specific to
* perfmon, we need to have a second level check to
* verify the source of the notification.
*/
task->thread.pfm_ovfl_block_reset = 1;
/*
* when coming from ctxsw, current still points to the
* previous task, therefore we must work with task and not current.
*/
info = ((struct thread_info *) ((char *) task + IA64_TASK_SIZE));
set_bit(TIF_NOTIFY_RESUME, &info->flags);
}
/* /*
* keep the PMU frozen until either pfm_restart() or * keep the PMU frozen until either pfm_restart() or
...@@ -3060,7 +3120,10 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str ...@@ -3060,7 +3120,10 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
*/ */
ctx->ctx_fl_frozen = 1; ctx->ctx_fl_frozen = 1;
DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n", DBprintk_ovfl(("current [%d] owner [%d] mode=%d return pmc0=0x%x must_block=%ld reason=%d\n",
current->pid,
PMU_OWNER() ? PMU_OWNER()->pid : -1,
mode,
ctx->ctx_fl_frozen ? 0x1 : 0x0, ctx->ctx_fl_frozen ? 0x1 : 0x0,
t->pfm_ovfl_block_reset, t->pfm_ovfl_block_reset,
ctx->ctx_fl_trap_reason)); ctx->ctx_fl_trap_reason));
...@@ -3115,13 +3178,15 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs) ...@@ -3115,13 +3178,15 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
/* /*
* assume PMC[0].fr = 1 at this point * assume PMC[0].fr = 1 at this point
*/ */
pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs); pmc0 = pfm_overflow_handler(0, task, ctx, pmc0, regs);
/* /*
* we can only update pmc0 when the overflow * we can only update pmc0 when the overflow
* is for the current context. In UP the current * is for the current context or we are in system
* task may not be the one owning the PMU * wide mode. In UP (per-task) the current
* task may not be the one owning the PMU,
* same thing for system-wide.
*/ */
if (task == current) { if (task == current || ctx->ctx_fl_system) {
/* /*
* We always clear the overflow status bits and either unfreeze * We always clear the overflow status bits and either unfreeze
* or keep the PMU frozen. * or keep the PMU frozen.
...@@ -3455,7 +3520,7 @@ pfm_load_regs (struct task_struct *task) ...@@ -3455,7 +3520,7 @@ pfm_load_regs (struct task_struct *task)
* Side effect on ctx_fl_frozen is possible. * Side effect on ctx_fl_frozen is possible.
*/ */
if (t->pmc[0] & ~0x1) { if (t->pmc[0] & ~0x1) {
t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL); t->pmc[0] = pfm_overflow_handler(1, task, ctx, t->pmc[0], NULL);
} }
/* /*
...@@ -3755,11 +3820,15 @@ pfm_inherit(struct task_struct *task, struct pt_regs *regs) ...@@ -3755,11 +3820,15 @@ pfm_inherit(struct task_struct *task, struct pt_regs *regs)
preempt_disable(); preempt_disable();
/* /*
* make sure child cannot mess up the monitoring session * for secure sessions, make sure child cannot mess up
* the monitoring session.
*/ */
ia64_psr(regs)->sp = 1; if (ctx->ctx_fl_unsecure == 0) {
DBprintk(("enabling psr.sp for [%d]\n", task->pid)); ia64_psr(regs)->sp = 1;
DBprintk(("enabling psr.sp for [%d]\n", task->pid));
} else {
DBprintk(("psr.sp=%d [%d]\n", ia64_psr(regs)->sp, task->pid));
}
/* /*
* if there was a virtual mapping for the sampling buffer * if there was a virtual mapping for the sampling buffer
......
...@@ -25,8 +25,8 @@ static pfm_reg_desc_t pfm_mck_pmc_desc[PMU_MAX_PMCS]={ ...@@ -25,8 +25,8 @@ static pfm_reg_desc_t pfm_mck_pmc_desc[PMU_MAX_PMCS]={
/* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL, pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL, pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
...@@ -143,11 +143,8 @@ pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *va ...@@ -143,11 +143,8 @@ pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *va
case 8: val8 = *val; case 8: val8 = *val;
val13 = th->pmc[13]; val13 = th->pmc[13];
val14 = th->pmc[14]; val14 = th->pmc[14];
*val |= 1UL << 2; /* bit 2 must always be 1 */
check_case1 = 1; check_case1 = 1;
break; break;
case 9: *val |= 1UL << 2; /* bit 2 must always be 1 */
break;
case 13: val8 = th->pmc[8]; case 13: val8 = th->pmc[8];
val13 = *val; val13 = *val;
val14 = th->pmc[14]; val14 = th->pmc[14];
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#define PFM_FL_NOTIFY_BLOCK 0x04 /* block task on user level notifications */ #define PFM_FL_NOTIFY_BLOCK 0x04 /* block task on user level notifications */
#define PFM_FL_SYSTEM_WIDE 0x08 /* create a system wide context */ #define PFM_FL_SYSTEM_WIDE 0x08 /* create a system wide context */
#define PFM_FL_EXCL_IDLE 0x20 /* exclude idle task from system wide session */ #define PFM_FL_EXCL_IDLE 0x20 /* exclude idle task from system wide session */
#define PFM_FL_UNSECURE 0x40 /* allow unsecure monitoring for non self-monitoring task */
/* /*
* PMC flags * PMC flags
...@@ -125,7 +126,7 @@ typedef struct { ...@@ -125,7 +126,7 @@ typedef struct {
* Define the version numbers for both perfmon as a whole and the sampling buffer format. * Define the version numbers for both perfmon as a whole and the sampling buffer format.
*/ */
#define PFM_VERSION_MAJ 1U #define PFM_VERSION_MAJ 1U
#define PFM_VERSION_MIN 3U #define PFM_VERSION_MIN 4U
#define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff)) #define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff))
#define PFM_SMPL_VERSION_MAJ 1U #define PFM_SMPL_VERSION_MAJ 1U
......
...@@ -291,7 +291,7 @@ struct thread_struct { ...@@ -291,7 +291,7 @@ struct thread_struct {
#define start_thread(regs,new_ip,new_sp) do { \ #define start_thread(regs,new_ip,new_sp) do { \
set_fs(USER_DS); \ set_fs(USER_DS); \
regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL | IA64_PSR_SP)) \ regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL)) \
& ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS)); \ & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS)); \
regs->cr_iip = new_ip; \ regs->cr_iip = new_ip; \
regs->ar_rsc = 0xf; /* eager mode, privilege level 3 */ \ regs->ar_rsc = 0xf; /* eager mode, privilege level 3 */ \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment