<html><body>
<p><tt>Paul Mackerras &lt;paulus@samba.org&gt; wrote on 05/15/2008 04:36:02 PM:<br>
<br>
&gt; Corey J Ashford writes:<br>
&gt; <br>
&gt; &gt; Ideally, what I'm looking for is something that mimics the operation of<br>
&gt; &gt; MASKABLE_EXCEPTION_PSERIES.<br>
&gt; &gt; I've been looking at the kernel code (entry_64.S, exception.h, head_64.S)<br>
&gt; &gt; but am finding it quite complicated and hard to follow, particularly in the<br>
&gt; &gt; area of interrupt disabling wrt the soft and hard disable logic.<br>
&gt; &gt; <br>
&gt; &gt; My initial thought is to do something like this in the beginning of my<br>
&gt; &gt; perfmon2 interrupt handler:<br>
&gt; &gt; <br>
&gt; &gt; void perfmon_pmu_int_handler(struct pt_regs *regs) {<br>
&gt; &gt; <br>
&gt; &gt; &nbsp; &nbsp; &nbsp; if (get_paca()-&gt;soft_enabled == 0) {<br>
&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* disable hardware interrupts */<br>
&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get_paca()-&gt;hard_enabled = 0;<br>
&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; regs-&gt;msr &amp;= ^MSR_EE;<br>
&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;<br>
&gt; &gt; &nbsp; &nbsp; &nbsp; }<br>
&gt; &gt; ...<br>
&gt; &gt; }<br>
&gt; &gt; <br>
&gt; &gt; Does this seem like it might work?<br>
&gt; <br>
&gt; That's a start (with ~MSR_EE rather than ^MSR_EE, of course). &nbsp;You<br>
&gt; also need to set a flag in that case, and test the flag in the part of<br>
&gt; arch/powerpc/kernel/irq.c:raw_local_irq_restore() that hard-enables<br>
&gt; interrupts. &nbsp;If the flag is set then you should call back into the<br>
&gt; perfmon2 code at that point (and clear the flag, of course). &nbsp;You<br>
&gt; could add a field to the paca for that flag.<br>
&gt; <br>
&gt; You probably also want to read some of the PMU's SPRs when you first<br>
&gt; get the interrupt and save their values away, and then when you get<br>
&gt; the call back from raw_local_irq_restore, use the saved values rather<br>
&gt; than what's currently in the SPRs, since the saved values will be more<br>
&gt; accurate.<br>
&gt; <br>
&gt; Paul.</tt><br>
<tt><br>
Hi Paul,</tt><br>
<br>
<tt>Thanks for the feedback. &nbsp;I don't believe I need a separate flag, because the PMU interrupt (via the PMAO bit) will still be pending when interrupts are hard enabled again, and the handler will be reentered automatically.</tt><br>
<br>
<tt>I'll think about the issue of caching the SPR values some more, but I don't want to complicate things too much. &nbsp;PMU event counts are not so critical that they need to so accurately reflect the exact value at the time of the interrupt.</tt><br>
<br>
<tt>I discovered through some trial and error that get_paca() doesn't work correctly in the interrupt handler. &nbsp;It appears that the value of r13 (the PACA pointer) is not initialized. &nbsp;Perhaps r13 is a scratch register used by the compiler?</tt><br>
<br>
<tt>Fortunately, because the soft enable flag is available in the pt_regs structure, and because the hard enable flag will be set to the same as the value of regs-&gt;msr's MSR_EE flag in the restore code, I now have this code in the interrupt handler:</tt><br>
<br>
<tt>void perfmon_pmu_int_handler(struct pt_regs *regs) {<br>
<br>
        if (regs-&gt;softe == 0) {<br>
                /* disable hardware interrupts */<br>
                regs-&gt;msr &amp;= ~MSR_EE;<br>
                return;</tt><br>
<tt>        }</tt><br>
<tt>        ...</tt><br>
<tt>}<br>
</tt><br>
<tt>This code does seem to be working, but needs more testing.</tt><br>
<br>
<tt>Regards,</tt><br>
<br>
<tt>- Corey</tt><br>
<br>
<tt>Corey Ashford<br>
Software Engineer<br>
IBM Linux Technology Center, Linux Toolchain<br>
Beaverton, OR <br>
503-578-3507 <br>
cjashfor@us.ibm.com<br>
</tt><br>
</body></html>