LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Linux controlling Hardware-Tasks on FPGA
From: David Hawkins @ 2006-07-19 16:15 UTC (permalink / raw)
  To: Josef Angermeier; +Cc: linuxppc-embedded
In-Reply-To: <44BDDFD2.9040702@cs.fau.de>


> anyone else out there using or wanting to use Linux to control the
> reconfiguration of a FPGA ? - Do you use dynamic partial reconfiguration
> too ? - If so how did you design the relevant software coarsely ?

Hi Josef,

If you are talking 'partial reconfiguration' then I guess you
are discussing Xilinx devices.

I use Altera devices in my designs. However, this solution could
work for you.

Generally an FPGA is configured, and I assume reconfigured,
by writing the configuration file to a specific set of pins
on the device. Altera devices have passive serial programming
and fast passive parallel programming (and other options).
In my current design I will create either a /dev entry or
use a /sys/firmware type interface that when opened
initializes the programming logic, and then writes whatever
bytes are written to the filesystem node to the programming
interface, eg. so the following will program the FPGA

dd if=firmware.bin of=/dev/fpga

If I get a programming error, then the driver can just return
-EIO, and I'm pretty sure dd will report the error. I plan
to use this approach as I can then buffer the data from user-space
into a kernel buffer, and then setup a DMA controller to
write to the device node. This will ensure that burst transactions
are used (to a system controller FPGA sitting on the local bus
of a PowerQUICC II Pro).

The alternative is to implement mmap() for the region containing
your programming interface control registers, and then just
bit- or byte-bang the programming interface. However, if the
serial interface is slow, then you could turn your 100MHz+ CPU
into a 1MHz- CPU. Linux sometimes has trouble with this
(I've seen the x86 kernel lose ticks when performing lots of
PCI I/O, so now use DMA when its available - which for x86
is basically never, so you have to depend on the adapter board).

Hope that gives you some ideas.

Regards
Dave

^ permalink raw reply

* MPC8260 SCC UART hardware flow control
From: Laurent Pinchart @ 2006-07-19 15:18 UTC (permalink / raw)
  To: linuxppc-embedded

Hi everybody,

I was wondering if anyone had implemented hardware flow control support in the 
cpm_uart driver. If not, I would appreciate pointers regarding how to do so.

Best regards,

Laurent Pinchart

^ permalink raw reply

* Re: reboot on PQ2FADS board.
From: Lei Sun @ 2006-07-19 14:12 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: linuxppc-embedded
In-Reply-To: <20060719063317.86A66352681@atlas.denx.de>

Hi :
  I  tried your approach last ight, (in fact I copied part of the
do_reboot() code from u-boot and put it in m8260_restart() function in
the kernel).  The only difference is the first line,
     volatile immap_t *immap = (immap_t *) IMAP_ADDR;
in my case it is
     volatile immap_t * immap = cpm2_immr;
I am using different source tree.
it simply hangs, rather then reset.

On 7/19/06, Wolfgang Denk <wd@denx.de> wrote:
> In message <4879B0C6C249214CBE7AB04453F84E4D050B0F@zch01exm20.fsl.freescale.net> you wrote:
> >
> > > command cause machine check and kernel ooops.  The problem seems in
> > > the "m8260_gorom" in head.S.  The restart() function in m8260_setup.c
> > > passed 2 parameters to that assembly code, r3 is the bd_info , r4 is
> > > the warm start address,  I changed it to 0xFF800100, that's where the
> > > u-boot's _start_warm lives, I have verified that address by typing "g
> > > ff800100" in u-boot console, which cause the board reset.
> >
> > Are you sure ff800100 is _start_warm lives?  In latest u-boot
>
> Trying to jump to some boot rom address is IMHO always a bad approach
> to reboot a system. You should always try to cause a reset  condition
> for  the CPU, and thus for all the associated hardware. On 8xx / 8260
> systems this is usually done by going through  a  machine  check.  We
> have  the  following code in our linuxppc_2_4_devel tree, which works
> on ALL 8260 systems, no matter whioch boot loder they use:
>
> static void
> m8260_restart(char *cmd)
> {
>        __volatile__ unsigned char dummy;
>        ulong msr;
>
>        cli();
>        volatile immap_t *immap = (immap_t *) IMAP_ADDR;
>
>        immap->im_clkrst.car_rmr = 1;    /* Checkstop Reset enable */
>
>        /* Interrupts and MMU off */
>        __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
>
>        msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
>        __asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
>
>        dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
>
>        printk("Restart failed\n");
>        for (;;);
> }
>
>
> Best regards,
>
> Wolfgang Denk
>
> --
> Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
> If a group of N persons implements a COBOL compiler,  there  will  be
> N-1 passes. Someone in the group has to be the manager. - T. Cheatham
>

^ permalink raw reply

* Re: [PATCH] Add USB to MPC8349 PB platform support
From: Kumar Gala @ 2006-07-19 13:14 UTC (permalink / raw)
  To: Li Yang-r58472; +Cc: linuxppc-dev, linux-usb-devel
In-Reply-To: <4879B0C6C249214CBE7AB04453F84E4D050B55@zch01exm20.fsl.freescale.net>


On Jul 19, 2006, at 1:30 AM, Li Yang-r58472 wrote:

>> -----Original Message-----
>> From: Kumar Gala [mailto:galak@kernel.crashing.org]
>> Sent: Tuesday, July 18, 2006 9:53 PM
>> To: Li Yang-r58472
>> Cc: Dan Malek; linuxppc-dev@ozlabs.org;
> linux-usb-devel@lists.sourceforge.net
>> Subject: Re: [PATCH] Add USB to MPC8349 PB platform support
>>
>> [snip]
>>
>>>> Well, I think there is a coupling that exists between whatever your
>>>> boot rom is and the kernel.  If you are trying to optimize boot
> time
>>>> I'd say one thing you would want is to avoid multiple writing the
>>>> same configuration registers.
>>>>
>>>> I dont have an issue if a fixed function board decides to do these
>>>> things in their kernel init instead of their boot rom.  I however,
>>>> don't want thousand and one config options to support all the
> various
>>>> ways one can configure the Freescale board.
>>>
>>> We won't have the thousand and one config options, making use of the
>>> device
>>> tree.  So this is not a problem.
>>
>> I'm talking about opening the door to a ton of options, not that we
>> have them now.  For example, your patch doesnt handle the USB PHYs if
>> they are on the MDS instead of the SYS board.  It doesn't handle
>> setting SCCR properly for different frequency choices.  I'm concerned
>> about where to draw the line because of all the ways a user can
>> configure the MDS board.
>
> My understanding is that in embedded world only this kind of versatile
> development boards needs to have Linux port in mainstream kernel.  A
> fixed function customer board used in embedded product will never get
> into kernel source.

This is an incorrect assumption.  Its more often that people dont  
post their ports to the Linux kernel for acceptance.  We will accept  
any port that is willing to work with the community.   for example

> The reasons for Freescale to provide this kind of boards are: first,
> verify functions on chip; second, demonstrate chip functions to
> customer; third, validate customer application on reference board;
> forth, help customer to build their own product by cutting down the
> board and software.
>
> Doing that, we do need some configure options to demonstrate main
> functions.  But there won't be too many options to confuse the user.
> Only key working modes are needed.  In your example, I think making  
> USB
> PHYs configurable for MDS is reasonable, but for SCCR it isn't as  
> it is
> well commented in code and is not likely to be modified.  Keep in mind
> that our only purpose is making customers easier and faster in
> developing their own products.

That's fine, however Freescale should figure out what the "common"  
modes of usage are before hand and document them.  Then the community  
can have a sense of the scope of what is needed and how to try to  
best accomplish that, and if anything is missing.

I disagree about the SCCR, I think its very reasonable for a customer  
to set the frequencies of their MDS board to match what their  
production system is going to be, which means the SCCR would need to  
be modified to match.

At the end of the day we will get some version of your patch into the  
kernel.  I just wanted to get some discussion on how we handle the  
reference boards that are extremely configurable.

- kumar

^ permalink raw reply

* [PATCH] force 64bit mode in fwnmi handlers to workaround firmware bugs
From: Olaf Hering @ 2006-07-19  8:34 UTC (permalink / raw)
  To: linuxppc-dev, Paul Mackeras
In-Reply-To: <20060522164111.GA14462@suse.de>


The firmware of POWER4 and JS20 systems does not switch the cpu to 64bit
mode when the registered system_reset and machine_check handlers get called.
If a 32bit process runs on that cpu at the time of the event, the cpu 
remains in 32bit mode. xmon and kdump can not deal with it, the result is
an error like 'Bad kernel stack pointer fff2aad0 at 3200'.
xmon just loses some register info, but booting the kdump kernel usually fails.

Both handlers are not hot paths.  Duplicate the EXCEPTION_PROLOG_PSERIES macro
and add two instructions to switch to 64bit:

 li     r11,5; 
 rldimi r10,r11,61,0; 


Signed-off-by: Olaf Hering <olh@suse.de>
---
 arch/powerpc/kernel/head_64.S |   35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

Index: linux-2.6.18-rc2/arch/powerpc/kernel/head_64.S
===================================================================
--- linux-2.6.18-rc2.orig/arch/powerpc/kernel/head_64.S
+++ linux-2.6.18-rc2/arch/powerpc/kernel/head_64.S
@@ -191,6 +191,37 @@ exception_marker:
 	ori	reg,reg,(label)@l;	/* virt addr of handler ... */
 #endif
 
+/*
+ * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
+ * The firmware calls the registered system_reset_fwnmi and
+ * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
+ * a 32bit application at the time of the event.
+ * This firmware bug is present on POWER4 and JS20.
+ */
+#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label)		\
+	mfspr	r13,SPRN_SPRG3;		/* get paca address into r13 */	\
+	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
+	std	r10,area+EX_R10(r13);					\
+	std	r11,area+EX_R11(r13);					\
+	std	r12,area+EX_R12(r13);					\
+	mfspr	r9,SPRN_SPRG1;						\
+	std	r9,area+EX_R13(r13);					\
+	mfcr	r9;							\
+	clrrdi	r12,r13,32;		/* get high part of &label */	\
+	mfmsr	r10;							\
+	/* force 64bit mode */						\
+	li	r11,5;			/* MSR_SF_LG|MSR_ISF_LG */	\
+	rldimi	r10,r11,61,0;		/* insert into top 3 bits */	\
+	/* done 64bit mode */						\
+	mfspr	r11,SPRN_SRR0;		/* save SRR0 */			\
+	LOAD_HANDLER(r12,label)						\
+	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI;				\
+	mtspr	SPRN_SRR0,r12;						\
+	mfspr	r12,SPRN_SRR1;		/* and SRR1 */			\
+	mtspr	SPRN_SRR1,r10;						\
+	rfid;								\
+	b	.	/* prevent speculative execution */
+
 #define EXCEPTION_PROLOG_PSERIES(area, label)				\
 	mfspr	r13,SPRN_SPRG3;		/* get paca address into r13 */	\
 	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
@@ -604,14 +635,14 @@ slb_miss_user_pseries:
 system_reset_fwnmi:
 	HMT_MEDIUM
 	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+	EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
 
 	.globl machine_check_fwnmi
       .align 7
 machine_check_fwnmi:
 	HMT_MEDIUM
 	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+	EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
 
 #ifdef CONFIG_PPC_ISERIES
 /***  ISeries-LPAR interrupt handlers ***/

^ permalink raw reply

* Re: [gmail] Linux bin Commands download
From: Marc Leeman @ 2006-07-19  7:21 UTC (permalink / raw)
  To: none none; +Cc: linuxppc-dev
In-Reply-To: <20060718123527.75952.qmail@web26204.mail.ukl.yahoo.com>

[-- Attachment #1: Type: text/plain, Size: 487 bytes --]

> I would like to download precompiled linux commands
> and programs for powerPC but i cannot find any
> binaries anyware. Are there any links?
> thanks in advance

You probably haven't been looking very hard (or at all). See e.g.
http://www.debian.org


-- 
  greetz, marc
It's not Kansas, and you're way too homely to be Auntie Em, but... Come
here, Toto.
	Crichton - That Old Black Magic
scorpius.homelinux.org 2.6.17 #2 PREEMPT Thu Jun 22 07:18:33 CEST 2006 GNU/Linux

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Linux controlling Hardware-Tasks on FPGA
From: Josef Angermeier @ 2006-07-19  7:31 UTC (permalink / raw)
  To: linuxppc-embedded


Hello,

anyone else out there using or wanting to use Linux to control the
reconfiguration of a FPGA ? - Do you use dynamic partial reconfiguration
too ? - If so how did you design the relevant software coarsely ?

thanks in advance,
Josef

^ permalink raw reply

* Re: reboot on PQ2FADS board.
From: Wolfgang Denk @ 2006-07-19  6:33 UTC (permalink / raw)
  To: Li Yang-r58472; +Cc: linuxppc-embedded
In-Reply-To: <4879B0C6C249214CBE7AB04453F84E4D050B0F@zch01exm20.fsl.freescale.net>

In message <4879B0C6C249214CBE7AB04453F84E4D050B0F@zch01exm20.fsl.freescale.net> you wrote:
>
> > command cause machine check and kernel ooops.  The problem seems in
> > the "m8260_gorom" in head.S.  The restart() function in m8260_setup.c
> > passed 2 parameters to that assembly code, r3 is the bd_info , r4 is
> > the warm start address,  I changed it to 0xFF800100, that's where the
> > u-boot's _start_warm lives, I have verified that address by typing "g
> > ff800100" in u-boot console, which cause the board reset.
> 
> Are you sure ff800100 is _start_warm lives?  In latest u-boot

Trying to jump to some boot rom address is IMHO always a bad approach
to reboot a system. You should always try to cause a reset  condition
for  the CPU, and thus for all the associated hardware. On 8xx / 8260
systems this is usually done by going through  a  machine  check.  We
have  the  following code in our linuxppc_2_4_devel tree, which works
on ALL 8260 systems, no matter whioch boot loder they use:

static void
m8260_restart(char *cmd)
{   
        __volatile__ unsigned char dummy;
        ulong msr;
    
        cli();
        volatile immap_t *immap = (immap_t *) IMAP_ADDR;
    
        immap->im_clkrst.car_rmr = 1;    /* Checkstop Reset enable */
    
        /* Interrupts and MMU off */
        __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
    
        msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
        __asm__ __volatile__ ("mtmsr    %0"::"r" (msr)); 
    
        dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
    
        printk("Restart failed\n");
        for (;;);
}   


Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
If a group of N persons implements a COBOL compiler,  there  will  be
N-1 passes. Someone in the group has to be the manager. - T. Cheatham

^ permalink raw reply

* RE: [PATCH] Add USB to MPC8349 PB platform support
From: Li Yang-r58472 @ 2006-07-19  6:30 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, linux-usb-devel
In-Reply-To: <41AD230F-91E8-442A-B9F9-9892D14BEF12@kernel.crashing.org>

> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Tuesday, July 18, 2006 9:53 PM
> To: Li Yang-r58472
> Cc: Dan Malek; linuxppc-dev@ozlabs.org;
linux-usb-devel@lists.sourceforge.net
> Subject: Re: [PATCH] Add USB to MPC8349 PB platform support
>=20
> [snip]
>=20
> >> Well, I think there is a coupling that exists between whatever your
> >> boot rom is and the kernel.  If you are trying to optimize boot
time
> >> I'd say one thing you would want is to avoid multiple writing the
> >> same configuration registers.
> >>
> >> I dont have an issue if a fixed function board decides to do these
> >> things in their kernel init instead of their boot rom.  I however,
> >> don't want thousand and one config options to support all the
various
> >> ways one can configure the Freescale board.
> >
> > We won't have the thousand and one config options, making use of the
> > device
> > tree.  So this is not a problem.
>=20
> I'm talking about opening the door to a ton of options, not that we
> have them now.  For example, your patch doesnt handle the USB PHYs if
> they are on the MDS instead of the SYS board.  It doesn't handle
> setting SCCR properly for different frequency choices.  I'm concerned
> about where to draw the line because of all the ways a user can
> configure the MDS board.

My understanding is that in embedded world only this kind of versatile
development boards needs to have Linux port in mainstream kernel.  A
fixed function customer board used in embedded product will never get
into kernel source.

The reasons for Freescale to provide this kind of boards are: first,
verify functions on chip; second, demonstrate chip functions to
customer; third, validate customer application on reference board;
forth, help customer to build their own product by cutting down the
board and software.

Doing that, we do need some configure options to demonstrate main
functions.  But there won't be too many options to confuse the user.
Only key working modes are needed.  In your example, I think making USB
PHYs configurable for MDS is reasonable, but for SCCR it isn't as it is
well commented in code and is not likely to be modified.  Keep in mind
that our only purpose is making customers easier and faster in
developing their own products.
>=20
> - kumar

^ permalink raw reply

* Re: [PATCH 2/3] powerpc: Instrument Hypervisor Calls: add wrappers
From: Mike Kravetz @ 2006-07-19  3:50 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060719033300.GA9451@pb15.lixom.net>

On Tue, Jul 18, 2006 at 10:33:00PM -0500, Olof Johansson wrote:
> If you use the FTR_SECTION stuff then it'll be taken care of
> automatically at boot time. Doing that from C is messy, I don't think
> anyone has had reason to do it before.

Ok, sounds like a good reason for assembly.  I'll dust off the books. :)

-- 
Mike

^ permalink raw reply

* RE: Linux bin Commands download
From: Li Yang-r58472 @ 2006-07-19  5:31 UTC (permalink / raw)
  To: none none, linuxppc-dev
In-Reply-To: <20060718123527.75952.qmail@web26204.mail.ukl.yahoo.com>

> -----Original Message-----
> From: linuxppc-dev-bounces+leoli=3Dfreescale.com@ozlabs.org
> [mailto:linuxppc-dev-bounces+leoli=3Dfreescale.com@ozlabs.org] On =
Behalf
Of none
> none
> Sent: Tuesday, July 18, 2006 8:35 PM
> To: linuxppc-dev@ozlabs.org
> Subject: Linux bin Commands download
>=20
> Hi
> I would like to download precompiled linux commands
> and programs for powerPC but i cannot find any
> binaries anyware. Are there any links?

You can find rpm at http://rpmfind.net.  And there are also a couple of
powerpc distributions out there.

> thanks in advance
> sotirakopoulos andreas

^ permalink raw reply

* RE: reboot on PQ2FADS board.
From: Li Yang-r58472 @ 2006-07-19  5:06 UTC (permalink / raw)
  To: Lei Sun, linuxppc-embedded
In-Reply-To: <f9a7e7a80607172040lcf0a280x5df9f44d10a0b7d6@mail.gmail.com>

> -----Original Message-----
> From: linuxppc-embedded-bounces+leoli=3Dfreescale.com@ozlabs.org
> [mailto:linuxppc-embedded-bounces+leoli=3Dfreescale.com@ozlabs.org] On
Behalf Of Lei Sun
> Sent: Tuesday, July 18, 2006 11:41 AM
> To: linuxppc-embedded@ozlabs.org
> Subject: reboot on PQ2FADS board.
>=20
> Hi:
>     I have linux 2.4.30 runnning on this board, the "reboot -f"
> command cause machine check and kernel ooops.  The problem seems in
> the "m8260_gorom" in head.S.  The restart() function in m8260_setup.c
> passed 2 parameters to that assembly code, r3 is the bd_info , r4 is
> the warm start address,  I changed it to 0xFF800100, that's where the
> u-boot's _start_warm lives, I have verified that address by typing "g
> ff800100" in u-boot console, which cause the board reset.

Are you sure ff800100 is _start_warm lives?  In latest u-boot
_start_warm is at
EXC_OFF_SYS_RESET + 0x10.  In your case, that will be 0xff800110.
Please try
with the correct address.

>     I assume the m8260_gorom  has been heavily tested for other
> boards. I wonder if anyone got a PQ2FADS-VR board that has the similar
> problem?  I am not familar with the assembly code for PPC.  Any
> suggestions?
>=20
> Thanks
> lei
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* Re: kernel memory map/usage/holes?
From: Sonny Rao @ 2006-07-19  4:47 UTC (permalink / raw)
  To: Chris Friesen; +Cc: linuxppc-dev
In-Reply-To: <44BBEDE1.3040004@nortel.com>

On Mon, Jul 17, 2006 at 02:06:57PM -0600, Chris Friesen wrote:
> 
> I've got a Maple board with 4GB of memory running a modified 2.6.10 
> kernel.  When it boots, I see the following in the logs:
> 
> 
> Top of RAM: 0x180000000, Total RAM: 0x100000000
> On node 0 totalpages: 1048576
>    DMA zone: 1048576 pages, LIFO batch:16
>    Normal zone: 0 pages, LIFO batch:1
>    HighMem zone: 0 pages, LIFO batch:1
> 
> 
> Then a bit later, I see:
> 
> 
> Memory: 4006976k/6291456k available (3408k kernel code, 2284124k 
> reserved, 1656k data, 448k bss, 220k init)
> 
> 
> 
> 1048576 pages works out to 4194304kB, so what happened to the 187328kB 
> that is the difference between the "Total RAM" and "Memory:" lines? 
> We've got an app that wants as much memory as possible, so I need to 
> explain where this 183MB of memory is being used.

I think it's part of the "reserved" category, which includes the MMU
hashtable.  I'd guess that's where it is.

Sonny

^ permalink raw reply

* Re: page locking in PowerPC cores
From: Parav Pandit @ 2006-07-19  4:45 UTC (permalink / raw)
  To: Eugene Surovegin; +Cc: linuxppc-embedded
In-Reply-To: <20060718233554.GA27549@gate.ebshome.net>


--- Eugene Surovegin <ebs@ebshome.net> wrote:
> >   We allocate memory for DMA operation on PCI
> device using pci_alloc_constistent().
> >    
> >   I want to know how this function is boil down to
> the actual instruction which locks the page in the
> RAM so that it cannot be paged out and dma can do
> its work.
> 
> This is trivial - you can start with looking at the
> implementation.
> 

[Parav]
I did it, but after reaching __alloc_pages() its
getting difficult to understand.
Here is the sequence:
pci_alloc_consistent()
-> __get_free_pages()
   ->alloc_pages(gfp_mask, order)
      ->alloc_pages_current()
         -> __alloc_pages()

It does something with zones. Looks like zone memory
pages are locked in the beginning.
Still could not figure out the instuctions for page
locking.


> >    
> >   Can anybody tell me which instructions do we use
> to set this page entry in TLB and page table?
> >   What bit gets set in the PTE for this?
> 
> Why do you need this page in TLB?

[Parav] No, I don't want. I just wanted to see the
code for locking inside TLB or in page table.


> 
> In general you don't have to worry about _any_
> memory you allocated in 
> the kernel to be paged out.
> 

[Parav] As driver writer, I agree I don't need to, but
to better understand the system I am eager to do that.

Regards,
Parav


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

^ permalink raw reply

* Re: [PATCH 2/3] powerpc: Instrument Hypervisor Calls: add wrappers
From: Olof Johansson @ 2006-07-19  3:33 UTC (permalink / raw)
  To: Mike Kravetz; +Cc: Olof Johansson, linuxppc-dev, Paul Mackerras
In-Reply-To: <20060718231815.GC3091@w-mikek2.ibm.com>

On Tue, Jul 18, 2006 at 04:18:15PM -0700, Mike Kravetz wrote:

> I assume checking must be done at run time via something like,
> if (cpu_has_feature(CPU_FTR_PURR))

If you do it in the hcall asm instead (like Paulus suggested), then it's
better to use BEGIN_FTR_SECTION/END_FTR_SECTION() around it, that way
the PURR reads just get nopped out instead of adding tests and branches.

> Also assume that it would make sense to do this determination at
> initialization/boot time and put the result in the statistic data
> structure.  In this way we would know it is in the same cache line
> we are updating with other stats.  Or, should cur_cpu_spec->cpu_features
> be 'sufficiently hot' to make this a non-issue?

If you use the FTR_SECTION stuff then it'll be taken care of
automatically at boot time. Doing that from C is messy, I don't think
anyone has had reason to do it before.


-Olof

^ permalink raw reply

* Re: [PATCH 0/3] powerpc: Instrument Hypervisor Calls
From: Mike Kravetz @ 2006-07-19  3:36 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17597.19430.983453.919592@cargo.ozlabs.ibm.com>

On Wed, Jul 19, 2006 at 07:00:22AM +1000, Paul Mackerras wrote:
> Mike Kravetz writes:
> > A small update from the last version.  By popular demand, both
> > wall time (mftb) and cpu cycles(PURR) are collected for each call.
> > It is interesting to see these two values side by side in the
> > output files.
> 
> Did you see the patch from Anton that I posted a week or so ago, which
> reduces the number of plpar_hcall_* functions?  I'd rather the
> instrumentation stuff was based on that.

Agreed.  I missed the patch from last week, but saw the one from Anton
that was posted today.  Future instrumentation patches will assume this
change.

> My other comment is this: wouldn't it actually turn out simpler if we
> read the timebase (and PURR, if we really want to do that too) in the
> assembly code that implements plpar_hcall_*?

I'll give that a try.  My assembly skills are a bit rusty, so it may
take a little longer to produce something.

-- 
Mike

^ permalink raw reply

* Re: page locking in PowerPC cores
From: Eugene Surovegin @ 2006-07-18 23:35 UTC (permalink / raw)
  To: Parav Pandit; +Cc: linuxppc-embedded
In-Reply-To: <20060718110350.28445.qmail@web36614.mail.mud.yahoo.com>

On Tue, Jul 18, 2006 at 04:03:50AM -0700, Parav Pandit wrote:
> Hi,
>    
>   We allocate memory for DMA operation on PCI device using pci_alloc_constistent().
>    
>   I want to know how this function is boil down to the actual instruction which locks the page in the RAM so that it cannot be paged out and dma can do its work.

This is trivial - you can start with looking at the implementation.

>    
>   Can anybody tell me which instructions do we use to set this page entry in TLB and page table?
>   What bit gets set in the PTE for this?

Why do you need this page in TLB?

In general you don't have to worry about _any_ memory you allocated in 
the kernel to be paged out.

-- 
Eugene

^ permalink raw reply

* Re: [PATCH 2/3] powerpc: Instrument Hypervisor Calls: add wrappers
From: Mike Kravetz @ 2006-07-18 23:18 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060718223425.GB5238@pb15.lixom.net>

On Tue, Jul 18, 2006 at 05:34:25PM -0500, Olof Johansson wrote:
> As I said before, SPRN_PURR doesn't exist on all architecture versions
> that supports hypervisor mode.

Thanks!

I assume checking must be done at run time via something like,
if (cpu_has_feature(CPU_FTR_PURR))

Also assume that it would make sense to do this determination at
initialization/boot time and put the result in the statistic data
structure.  In this way we would know it is in the same cache line
we are updating with other stats.  Or, should cur_cpu_spec->cpu_features
be 'sufficiently hot' to make this a non-issue?

-- 
Mike

^ permalink raw reply

* Re: [PATCH 0/3] powerpc: Instrument Hypervisor Calls
From: Olof Johansson @ 2006-07-18 22:38 UTC (permalink / raw)
  To: Mike Kravetz; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060718212913.GB3091@w-mikek2.ibm.com>

On Tue, Jul 18, 2006 at 02:29:13PM -0700, Mike Kravetz wrote:

> 88 1046 108106 109322
[...]
> 104 1 1040 1061

Heh. Shouldn't PURR/TB be <= 1 at all times? :-) I bet this is because
they're not sampled at exactly the same time, etc.

Maybe recoding it to assembly so you can do mftb and mfspr right after
each other, and do the arithmetics/stores later could help. Inline asm
might be sufficient.


-Olof

^ permalink raw reply

* Re: [PATCH 2/3] powerpc: Instrument Hypervisor Calls: add wrappers
From: Olof Johansson @ 2006-07-18 22:34 UTC (permalink / raw)
  To: Mike Kravetz; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060718204946.GC6104@w-mikek2.ibm.com>

On Tue, Jul 18, 2006 at 01:49:46PM -0700, Mike Kravetz wrote:
> Add wrappers which perform the actual hypervisor call instrumentation.
> --
> Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>

NACK.

As I said before, SPRN_PURR doesn't exist on all architecture versions
that supports hypervisor mode. Try booting on a JS20/21 or a POWER4
machine in LPAR mode and you'll see. (Unfortunately I don't have access
to any such hardware myself, so I can't send you oops output to show it).


-Olof

> diff -Naupr linux-2.6.17.6/arch/powerpc/Kconfig.debug linux-2.6.17.6.work/arch/powerpc/Kconfig.debug
> --- linux-2.6.17.6/arch/powerpc/Kconfig.debug	2006-07-15 19:00:43.000000000 +0000
> +++ linux-2.6.17.6.work/arch/powerpc/Kconfig.debug	2006-07-18 19:56:20.000000000 +0000
> @@ -18,6 +18,20 @@ config DEBUG_STACK_USAGE
>  
>  	  This option will slow down process creation somewhat.
>  
> +config HCALL_STATS
> +	bool "Hypervisor call instrumentation"
> +	depends on PPC_PSERIES && DEBUG_FS
> +	help
> +	  Adds code to keep track of the number of hypervisor calls made and
> +	  the amount of time spent in hypervisor calls: both wall time (based
> +	  on time base) and cpu time (based on PURR).  A directory named
> +	  hcall_inst is added at the root of the debugfs filesystem.  Within
> +	  the hcall_inst directory are files that contain CPU specific call
> +	  statistics.
> +
> +	  This option will add a small amount of overhead to all hypervisor
> +	  calls.
> +
>  config DEBUGGER
>  	bool "Enable debugger hooks"
>  	depends on DEBUG_KERNEL
> diff -Naupr linux-2.6.17.6/arch/powerpc/platforms/pseries/Makefile linux-2.6.17.6.work/arch/powerpc/platforms/pseries/Makefile
> --- linux-2.6.17.6/arch/powerpc/platforms/pseries/Makefile	2006-07-15 19:00:43.000000000 +0000
> +++ linux-2.6.17.6.work/arch/powerpc/platforms/pseries/Makefile	2006-07-18 19:56:20.000000000 +0000
> @@ -9,3 +9,4 @@ obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o e
>  
>  obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
>  obj-$(CONFIG_HVCS)		+= hvcserver.o
> +obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
> diff -Naupr linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall.S linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall.S
> --- linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall.S	2006-07-15 19:00:43.000000000 +0000
> +++ linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall.S	2006-07-18 19:56:20.000000000 +0000
> @@ -11,7 +11,35 @@
>  #include <asm/hvcall.h>
>  #include <asm/processor.h>
>  #include <asm/ppc_asm.h>
> -	
> +
> +/*
> + * If hcall statistics are desired, all routines are wrapped with code
> + * that does the statistic gathering.
> + */
> +#ifndef CONFIG_HCALL_STATS
> +#define PLPAR_HCALL		plpar_hcall
> +#define PLPAR_HCALL_NORETS	plpar_hcall_norets
> +#define PLPAR_HCALL_8ARG_2RET	plpar_hcall_8arg_2ret
> +#define PLPAR_HCALL_4OUT	plpar_hcall_4out
> +#define PLPAR_HCALL_7ARG_7RET	plpar_hcall_7arg_7ret
> +#define PLPAR_HCALL_9ARG_9RET	plpar_hcall_9arg_9ret
> +#else
> +#define PLPAR_HCALL		plpar_hcall_base
> +#define PLPAR_HCALL_NORETS	plpar_hcall_norets_base
> +#define PLPAR_HCALL_8ARG_2RET	plpar_hcall_8arg_2ret_base
> +#define PLPAR_HCALL_4OUT	plpar_hcall_4out_base
> +#define PLPAR_HCALL_7ARG_7RET	plpar_hcall_7arg_7ret_base
> +#define PLPAR_HCALL_9ARG_9RET	plpar_hcall_9arg_9ret_base
> +
> +/*
> + * A special 'indirect' call to a C based wrapper if statistics are desired.
> + * See plpar_hcall_norets_C function header for more details.
> + */
> +_GLOBAL(plpar_hcall_norets)
> +	b	plpar_hcall_norets_C
> +
> +#endif
> +
>  #define STK_PARM(i)     (48 + ((i)-3)*8)
>  
>  	.text
> @@ -25,7 +53,7 @@
>  			unsigned long *out2,		R9
>  			unsigned long *out3);		R10
>   */
> -_GLOBAL(plpar_hcall)
> +_GLOBAL(PLPAR_HCALL)
>  	HMT_MEDIUM
>  
>  	mfcr	r0
> @@ -52,7 +80,7 @@ _GLOBAL(plpar_hcall)
>  
>  
>  /* Simple interface with no output values (other than status) */
> -_GLOBAL(plpar_hcall_norets)
> +_GLOBAL(PLPAR_HCALL_NORETS)
>  	HMT_MEDIUM
>  
>  	mfcr	r0
> @@ -76,7 +104,7 @@ _GLOBAL(plpar_hcall_norets)
>  			unsigned long arg8,		112(R1)
>  			unsigned long *out1);		120(R1)
>   */
> -_GLOBAL(plpar_hcall_8arg_2ret)
> +_GLOBAL(PLPAR_HCALL_8ARG_2RET)
>  	HMT_MEDIUM
>  
>  	mfcr	r0
> @@ -102,7 +130,7 @@ _GLOBAL(plpar_hcall_8arg_2ret)
>  		 	unsigned long *out3,		R10
>  		 	unsigned long *out4);		112(R1)
>   */
> -_GLOBAL(plpar_hcall_4out)
> +_GLOBAL(PLPAR_HCALL_4OUT)
>  	HMT_MEDIUM
>  
>  	mfcr	r0
> @@ -144,7 +172,7 @@ _GLOBAL(plpar_hcall_4out)
>  			 unsigned long *out6,		102(R1)
>  			 unsigned long *out7);		100(R1)
>  */
> -_GLOBAL(plpar_hcall_7arg_7ret)
> +_GLOBAL(PLPAR_HCALL_7ARG_7RET)
>  	HMT_MEDIUM
>  
>  	mfcr	r0
> @@ -193,7 +221,7 @@ _GLOBAL(plpar_hcall_7arg_7ret)
>  			 unsigned long *out8,		 94(R1)
>  		         unsigned long *out9,            92(R1)
>  */
> -_GLOBAL(plpar_hcall_9arg_9ret)
> +_GLOBAL(PLPAR_HCALL_9ARG_9RET)
>  	HMT_MEDIUM
>  
>  	mfcr	r0
> diff -Naupr linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall_inst.c linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall_inst.c
> --- linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall_inst.c	1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall_inst.c	2006-07-18 19:57:44.000000000 +0000
> @@ -0,0 +1,216 @@
> +/*
> + * Copyright (C) 2006 Mike Kravetz IBM Corporation
> + *
> + * Hypervisor Call Instrumentation
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/percpu.h>
> +#include <linux/debugfs.h>
> +#include <linux/seq_file.h>
> +#include <linux/cpumask.h>
> +#include <asm/hvcall.h>
> +#include <asm/firmware.h>
> +
> +DEFINE_PER_CPU(struct hcall_stats[MAX_HCALL_OPCODES+1], hcall_stats);
> +
> +/*
> + * Common update of the per-CPU/per-hcall statistics
> + */
> +static inline void update_stats(unsigned long opcode,
> +				unsigned long t_tb_before,
> +				unsigned long t_cpu_before)
> +{
> +	unsigned long op_index = opcode >> 2;
> +	struct hcall_stats *hs = &__get_cpu_var(hcall_stats[op_index]);
> +
> +	hs->tb_total += (mftb() - t_tb_before);
> +	hs->cpu_total += (mfspr(SPRN_PURR) - t_cpu_before);
> +	hs->num_calls++;
> +}
> +
> +/*
> + * plpar_hcall wrapper
> + */
> +long plpar_hcall(unsigned long opcode,
> +                 unsigned long arg1,
> +                 unsigned long arg2,
> +                 unsigned long arg3,
> +                 unsigned long arg4,
> +                 unsigned long *out1,
> +                 unsigned long *out2,
> +                 unsigned long *out3)
> +{
> +	long rc;
> +	unsigned long t_tb_before, t_cpu_before;
> +
> +	t_tb_before = mftb();
> +	t_cpu_before = mfspr(SPRN_PURR);
> +	rc = plpar_hcall_base(opcode, arg1, arg2, arg3, arg4, out1, out2, out3);
> +
> +	update_stats(opcode, t_tb_before, t_cpu_before);
> +	return rc;
> +}
> +
> +/*
> + * A C based wrapper for plpar_hcall_norets
> + * The wrapper for plpar_hcall_norets is a special case because the function
> + * takes a variable number of arguments.  It is almost impossible to write a
> + * wrapper for a function that takes a variable number of arguments in C.
> + * Therefore, there is an assembly routine in hvCall.S that simply branches
> + * to this C wrapper.  This 'indirection' takes care of the variable arguments
> + * issue.  This C wrapper has a fixed maximum number of arguments.
> + */
> +long plpar_hcall_norets_C(unsigned long opcode,
> +				unsigned long arg1,
> +				unsigned long arg2,
> +				unsigned long arg3,
> +				unsigned long arg4,
> +				unsigned long arg5,
> +				unsigned long arg6)
> +{
> +	long rc;
> +	unsigned long t_tb_before, t_cpu_before;
> +
> +	t_tb_before = mftb();
> +	t_cpu_before = mfspr(SPRN_PURR);
> +	rc = plpar_hcall_norets_base(opcode, arg1, arg2, arg3, arg4, arg5,
> +				     arg6);
> +
> +	update_stats(opcode, t_tb_before, t_cpu_before);
> +	return rc;
> +}
> +
> +/*
> + * plpar_hcall_8arg_2ret wrapper
> + */
> +long plpar_hcall_8arg_2ret(unsigned long opcode,
> +                           unsigned long arg1,
> +                           unsigned long arg2,
> +                           unsigned long arg3,
> +                           unsigned long arg4,
> +                           unsigned long arg5,
> +                           unsigned long arg6,
> +                           unsigned long arg7,
> +                           unsigned long arg8,
> +                           unsigned long *out1)
> +{
> +	long rc;
> +	unsigned long t_tb_before, t_cpu_before;
> +
> +	t_tb_before = mftb();
> +	t_cpu_before = mfspr(SPRN_PURR);
> +	rc = plpar_hcall_8arg_2ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
> +					arg6, arg7, arg8, out1);
> +
> +	update_stats(opcode, t_tb_before, t_cpu_before);
> +	return rc;
> +}
> +
> +/*
> + * plpar_hcall_4out wrapper
> + */
> +long plpar_hcall_4out(unsigned long opcode,
> +                      unsigned long arg1,
> +                      unsigned long arg2,
> +                      unsigned long arg3,
> +                      unsigned long arg4,
> +                      unsigned long *out1,
> +                      unsigned long *out2,
> +                      unsigned long *out3,
> +                      unsigned long *out4)
> +{
> +	long rc;
> +	unsigned long t_tb_before, t_cpu_before;
> +
> +	t_tb_before = mftb();
> +	t_cpu_before = mfspr(SPRN_PURR);
> +	rc = plpar_hcall_4out_base(opcode, arg1, arg2, arg3, arg4, out1,
> +				   out2, out3, out4);
> +
> +	update_stats(opcode, t_tb_before, t_cpu_before);
> +	return rc;
> +}
> +
> +/*
> + * plpar_hcall_7arg_7ret wrapper
> + */
> +long plpar_hcall_7arg_7ret(unsigned long opcode,
> +                           unsigned long arg1,
> +                           unsigned long arg2,
> +                           unsigned long arg3,
> +                           unsigned long arg4,
> +                           unsigned long arg5,
> +                           unsigned long arg6,
> +                           unsigned long arg7,
> +                           unsigned long *out1,
> +                           unsigned long *out2,
> +                           unsigned long *out3,
> +                           unsigned long *out4,
> +                           unsigned long *out5,
> +                           unsigned long *out6,
> +                           unsigned long *out7)
> +{
> +	long rc;
> +	unsigned long t_tb_before, t_cpu_before;
> +
> +	t_tb_before = mftb();
> +	t_cpu_before = mfspr(SPRN_PURR);
> +	rc = plpar_hcall_7arg_7ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
> +					arg6, arg7, out1, out2, out3, out4,
> +					out5, out6, out7);
> +
> +	update_stats(opcode, t_tb_before, t_cpu_before);
> +	return rc;
> +}
> +
> +/*
> + * plpar_hcall_9arg_9ret wrapper
> + */
> +long plpar_hcall_9arg_9ret(unsigned long opcode,
> +                           unsigned long arg1,
> +                           unsigned long arg2,
> +                           unsigned long arg3,
> +                           unsigned long arg4,
> +                           unsigned long arg5,
> +                           unsigned long arg6,
> +                           unsigned long arg7,
> +                           unsigned long arg8,
> +                           unsigned long arg9,
> +                           unsigned long *out1,
> +                           unsigned long *out2,
> +                           unsigned long *out3,
> +                           unsigned long *out4,
> +                           unsigned long *out5,
> +                           unsigned long *out6,
> +                           unsigned long *out7,
> +                           unsigned long *out8,
> +                           unsigned long *out9)
> +{
> +	long rc;
> +	unsigned long t_tb_before, t_cpu_before;
> +
> +	t_tb_before = mftb();
> +	t_cpu_before = mfspr(SPRN_PURR);
> +	rc = plpar_hcall_9arg_9ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
> +					arg6, arg7, arg8, arg9, out1, out2,
> +					out3, out4, out5, out6, out7, out8,
> +					out9);
> +
> +	update_stats(opcode, t_tb_before, t_cpu_before);
> +	return rc;
> +}
> diff -Naupr linux-2.6.17.6/include/asm-powerpc/hvcall.h linux-2.6.17.6.work/include/asm-powerpc/hvcall.h
> --- linux-2.6.17.6/include/asm-powerpc/hvcall.h	2006-07-18 19:35:00.000000000 +0000
> +++ linux-2.6.17.6.work/include/asm-powerpc/hvcall.h	2006-07-18 19:56:20.000000000 +0000
> @@ -292,6 +292,87 @@ long plpar_hcall_9arg_9ret(unsigned long
>  			   unsigned long *out8,
>  			   unsigned long *out9);
>  
> +
> +/* For hcall instrumentation.  One structure per-hcall, per-CPU */
> +struct hcall_stats {
> +	unsigned long	num_calls;	/* number of calls (on this CPU) */
> +	unsigned long	tb_total;	/* total wall time (mftb) of calls. */
> +	unsigned long	cpu_total;	/* total cpu time (PURR) of calls. */
> +};
> +
> +/* If Hypervisor call instrumentation is enabled, the assembly routine
> + * names are changed from 'plpar_hcall*' to 'plpar_hcall*_base' and
> + * 'plpar_hcall*' routines become instrumented wrappers.  The following
> + * are declarations for the renamed 'plpar_hcall*_base' routines.
> + */
> +long plpar_hcall_base (unsigned long opcode,
> +		       unsigned long arg1,
> +		       unsigned long arg2,
> +		       unsigned long arg3,
> +		       unsigned long arg4,
> +		       unsigned long *out1,
> +		       unsigned long *out2,
> +		       unsigned long *out3);
> +
> +long plpar_hcall_norets_base(unsigned long opcode, ...);
> +
> +long plpar_hcall_8arg_2ret_base(unsigned long opcode,
> +				unsigned long arg1,
> +				unsigned long arg2,
> +				unsigned long arg3,
> +				unsigned long arg4,
> +				unsigned long arg5,
> +				unsigned long arg6,
> +				unsigned long arg7,
> +				unsigned long arg8,
> +				unsigned long *out1);
> +
> +long plpar_hcall_4out_base(unsigned long opcode,
> +			   unsigned long arg1,
> +			   unsigned long arg2,
> +			   unsigned long arg3,
> +			   unsigned long arg4,
> +			   unsigned long *out1,
> +			   unsigned long *out2,
> +			   unsigned long *out3,
> +			   unsigned long *out4);
> +
> +long plpar_hcall_7arg_7ret_base(unsigned long opcode,
> +				unsigned long arg1,
> +				unsigned long arg2,
> +				unsigned long arg3,
> +				unsigned long arg4,
> +				unsigned long arg5,
> +				unsigned long arg6,
> +				unsigned long arg7,
> +				unsigned long *out1,
> +				unsigned long *out2,
> +				unsigned long *out3,
> +				unsigned long *out4,
> +				unsigned long *out5,
> +				unsigned long *out6,
> +				unsigned long *out7);
> +
> +long plpar_hcall_9arg_9ret_base(unsigned long opcode,
> +				unsigned long arg1,
> +				unsigned long arg2,
> +				unsigned long arg3,
> +				unsigned long arg4,
> +				unsigned long arg5,
> +				unsigned long arg6,
> +				unsigned long arg7,
> +				unsigned long arg8,
> +				unsigned long arg9,
> +				unsigned long *out1,
> +				unsigned long *out2,
> +				unsigned long *out3,
> +				unsigned long *out4,
> +				unsigned long *out5,
> +				unsigned long *out6,
> +				unsigned long *out7,
> +				unsigned long *out8,
> +				unsigned long *out9);
> +
>  #endif /* __ASSEMBLY__ */
>  #endif /* __KERNEL__ */
>  #endif /* _ASM_POWERPC_HVCALL_H */
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* [PATCH] clean up pseries hcall interfaces
From: Anton Blanchard @ 2006-07-18 22:01 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus


Our pseries hcall interfaces are out of control:

	plpar_hcall_norets
	plpar_hcall
	plpar_hcall_8arg_2ret
	plpar_hcall_4out
	plpar_hcall_7arg_7ret
	plpar_hcall_9arg_9ret

Create 3 interfaces to cover all cases:

	plpar_hcall_norets:	7 arguments no returns
	plpar_hcall:		6 arguments 4 returns
	plpar_hcall9:		9 arguments 9 returns

There are only 2 cases in the kernel that need plpar_hcall9, hopefully
we can keep it that way.

Pass in a buffer to stash return parameters so we avoid the &dummy1,
&dummy2 madness.

Signed-off-by: Anton Blanchard <anton@samba.org>
--

Index: build/arch/powerpc/kernel/lparcfg.c
===================================================================
--- build.orig/arch/powerpc/kernel/lparcfg.c	2006-07-18 04:20:13.000000000 +1000
+++ build/arch/powerpc/kernel/lparcfg.c	2006-07-18 04:24:08.000000000 +1000
@@ -183,8 +183,14 @@ static unsigned int h_get_ppp(unsigned l
 			      unsigned long *resource)
 {
 	unsigned long rc;
-	rc = plpar_hcall_4out(H_GET_PPP, 0, 0, 0, 0, entitled, unallocated,
-			      aggregation, resource);
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall(H_GET_PPP, retbuf);
+
+	*entitled = retbuf[0];
+	*unallocated = retbuf[1];
+	*aggregation = retbuf[2];
+	*resource = retbuf[3];
 
 	log_plpar_hcall_return(rc, "H_GET_PPP");
 
@@ -194,8 +200,12 @@ static unsigned int h_get_ppp(unsigned l
 static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
 {
 	unsigned long rc;
-	unsigned long dummy;
-	rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall(H_PIC, retbuf);
+
+	*pool_idle_time = retbuf[0];
+	*num_procs = retbuf[1];
 
 	if (rc != H_AUTHORITY)
 		log_plpar_hcall_return(rc, "H_PIC");
Index: build/arch/powerpc/kernel/rtas.c
===================================================================
--- build.orig/arch/powerpc/kernel/rtas.c	2006-07-18 04:20:13.000000000 +1000
+++ build/arch/powerpc/kernel/rtas.c	2006-07-18 04:24:08.000000000 +1000
@@ -666,15 +666,14 @@ static int rtas_ibm_suspend_me(struct rt
 	int i;
 	long state;
 	long rc;
-	unsigned long dummy;
-
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
 	struct rtas_suspend_me_data data;
 
 	/* Make sure the state is valid */
-	rc = plpar_hcall(H_VASI_STATE,
-			 ((u64)args->args[0] << 32) | args->args[1],
-			 0, 0, 0,
-			 &state, &dummy, &dummy);
+	rc = plpar_hcall(H_VASI_STATE, retbuf,
+			 ((u64)args->args[0] << 32) | args->args[1]);
+
+	state = retbuf[0];
 
 	if (rc) {
 		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
Index: build/arch/powerpc/platforms/pseries/hvCall.S
===================================================================
--- build.orig/arch/powerpc/platforms/pseries/hvCall.S	2006-07-18 04:20:13.000000000 +1000
+++ build/arch/powerpc/platforms/pseries/hvCall.S	2006-07-19 06:59:32.000000000 +1000
@@ -1,7 +1,6 @@
 /*
  * This file contains the generic code to perform a call to the
  * pSeries LPAR hypervisor.
- * NOTE: this file will go away when we move to inline this work.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -16,42 +15,6 @@
 
 	.text
 
-/* long plpar_hcall(unsigned long opcode,		R3
-			unsigned long arg1,		R4
-			unsigned long arg2,		R5
-			unsigned long arg3,		R6
-			unsigned long arg4,		R7
-			unsigned long *out1,		R8
-			unsigned long *out2,		R9
-			unsigned long *out3);		R10
- */
-_GLOBAL(plpar_hcall)
-	HMT_MEDIUM
-
-	mfcr	r0
-
-	std	r8,STK_PARM(r8)(r1)	/* Save out ptrs */
-	std	r9,STK_PARM(r9)(r1)
-	std	r10,STK_PARM(r10)(r1)
-
-	stw	r0,8(r1)
-
-	HVSC				/* invoke the hypervisor */
-
-	lwz	r0,8(r1)
-
-	ld	r8,STK_PARM(r8)(r1)	/* Fetch r4-r6 ret args */
-	ld	r9,STK_PARM(r9)(r1)
-	ld	r10,STK_PARM(r10)(r1)
-	std	r4,0(r8)
-	std	r5,0(r9)
-	std	r6,0(r10)
-
-	mtcrf	0xff,r0
-	blr				/* return r3 = status */
-
-
-/* Simple interface with no output values (other than status) */
 _GLOBAL(plpar_hcall_norets)
 	HMT_MEDIUM
 
@@ -64,164 +27,64 @@ _GLOBAL(plpar_hcall_norets)
 	mtcrf	0xff,r0
 	blr				/* return r3 = status */
 
-
-/* long plpar_hcall_8arg_2ret(unsigned long opcode,	R3
-			unsigned long arg1,		R4
-			unsigned long arg2,		R5
-			unsigned long arg3,		R6
-			unsigned long arg4,		R7
-			unsigned long arg5,		R8
-			unsigned long arg6,		R9
-			unsigned long arg7,		R10
-			unsigned long arg8,		112(R1)
-			unsigned long *out1);		120(R1)
- */
-_GLOBAL(plpar_hcall_8arg_2ret)
+_GLOBAL(plpar_hcall)
 	HMT_MEDIUM
 
 	mfcr	r0
-	ld	r11,STK_PARM(r11)(r1)	/* put arg8 in R11 */
 	stw	r0,8(r1)
 
-	HVSC				/* invoke the hypervisor */
-
-	lwz	r0,8(r1)
-	ld	r10,STK_PARM(r12)(r1)	/* Fetch r4 ret arg */
-	std	r4,0(r10)
-	mtcrf	0xff,r0
-	blr				/* return r3 = status */
-
-
-/* long plpar_hcall_4out(unsigned long opcode,		R3
-		 	unsigned long arg1,		R4
-		 	unsigned long arg2,		R5
-		 	unsigned long arg3,		R6
-		 	unsigned long arg4,		R7
-		 	unsigned long *out1,		R8
-		 	unsigned long *out2,		R9
-		 	unsigned long *out3,		R10
-		 	unsigned long *out4);		112(R1)
- */
-_GLOBAL(plpar_hcall_4out)
-	HMT_MEDIUM
-
-	mfcr	r0
-	stw	r0,8(r1)
+	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
 
-	std	r8,STK_PARM(r8)(r1)	/* Save out ptrs */
-	std	r9,STK_PARM(r9)(r1)
-	std	r10,STK_PARM(r10)(r1)
+	mr	r4,r5
+	mr	r5,r6
+	mr	r6,r7
+	mr	r7,r8
+	mr	r8,r9
+	mr	r9,r10
 
 	HVSC				/* invoke the hypervisor */
 
-	lwz	r0,8(r1)
-
-	ld	r8,STK_PARM(r8)(r1)	/* Fetch r4-r7 ret args */
-	ld	r9,STK_PARM(r9)(r1)
-	ld	r10,STK_PARM(r10)(r1)
-	ld	r11,STK_PARM(r11)(r1)
-	std	r4,0(r8)
-	std	r5,0(r9)
-	std	r6,0(r10)
-	std	r7,0(r11)
-
-	mtcrf	0xff,r0
-	blr				/* return r3 = status */
-
-/* plpar_hcall_7arg_7ret(unsigned long opcode,		R3
-			 unsigned long arg1,		R4
-			 unsigned long arg2,		R5
-			 unsigned long arg3,		R6
-			 unsigned long arg4,		R7
-			 unsigned long arg5,		R8
-			 unsigned long arg6,		R9
-			 unsigned long arg7,		R10
-			 unsigned long *out1,		112(R1)
-			 unsigned long *out2,		110(R1)
-			 unsigned long *out3,		108(R1)
-			 unsigned long *out4,		106(R1)
-			 unsigned long *out5,		104(R1)
-			 unsigned long *out6,		102(R1)
-			 unsigned long *out7);		100(R1)
-*/
-_GLOBAL(plpar_hcall_7arg_7ret)
-	HMT_MEDIUM
-
-	mfcr	r0
-	stw	r0,8(r1)
-
-	HVSC				/* invoke the hypervisor */
+	ld	r12,STK_PARM(r4)(r1)
+	std	r4,  0(r12)
+	std	r5,  8(r12)
+	std	r6, 16(r12)
+	std	r7, 24(r12)
 
 	lwz	r0,8(r1)
-
-	ld	r11,STK_PARM(r11)(r1)	/* Fetch r4 ret arg */
-	std	r4,0(r11)
-	ld	r11,STK_PARM(r12)(r1)	/* Fetch r5 ret arg */
-	std	r5,0(r11)
-	ld	r11,STK_PARM(r13)(r1)	/* Fetch r6 ret arg */
-	std	r6,0(r11)
-	ld	r11,STK_PARM(r14)(r1)	/* Fetch r7 ret arg */
-	std	r7,0(r11)
-	ld	r11,STK_PARM(r15)(r1)	/* Fetch r8 ret arg */
-	std	r8,0(r11)
-	ld	r11,STK_PARM(r16)(r1)	/* Fetch r9 ret arg */
-	std	r9,0(r11)
-	ld	r11,STK_PARM(r17)(r1)	/* Fetch r10 ret arg */
-	std	r10,0(r11)
-
 	mtcrf	0xff,r0
 
 	blr				/* return r3 = status */
 
-/* plpar_hcall_9arg_9ret(unsigned long opcode,		R3
-			 unsigned long arg1,		R4
-			 unsigned long arg2,		R5
-			 unsigned long arg3,		R6
-			 unsigned long arg4,		R7
-			 unsigned long arg5,		R8
-			 unsigned long arg6,		R9
-			 unsigned long arg7,		R10
-			 unsigned long arg8,		112(R1)
-			 unsigned long arg9,		110(R1)
-			 unsigned long *out1,		108(R1)
-			 unsigned long *out2,		106(R1)
-			 unsigned long *out3,		104(R1)
-			 unsigned long *out4,		102(R1)
-			 unsigned long *out5,		100(R1)
-			 unsigned long *out6,		 98(R1)
-			 unsigned long *out7);		 96(R1)
-			 unsigned long *out8,		 94(R1)
-		         unsigned long *out9,            92(R1)
-*/
-_GLOBAL(plpar_hcall_9arg_9ret)
+_GLOBAL(plpar_hcall9)
 	HMT_MEDIUM
 
 	mfcr	r0
 	stw	r0,8(r1)
 
-	ld	r11,STK_PARM(r11)(r1)	 /* put arg8 in R11 */
-	ld	r12,STK_PARM(r12)(r1)    /* put arg9 in R12 */
+	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
+
+	mr	r4,r5
+	mr	r5,r6
+	mr	r6,r7
+	mr	r7,r8
+	mr	r8,r9
+	mr	r9,r10
+	ld	r10,STK_PARM(r11)(r1)	 /* put arg7 in R10 */
+	ld	r11,STK_PARM(r12)(r1)	 /* put arg8 in R11 */
+	ld	r12,STK_PARM(r13)(r1)    /* put arg9 in R12 */
 
 	HVSC				/* invoke the hypervisor */
 
-	ld	r0,STK_PARM(r13)(r1)	/* Fetch r4 ret arg */
-	stdx	r4,r0,r0
-	ld	r0,STK_PARM(r14)(r1)	/* Fetch r5 ret arg */
-	stdx	r5,r0,r0
-	ld	r0,STK_PARM(r15)(r1)	/* Fetch r6 ret arg */
-	stdx	r6,r0,r0
-	ld	r0,STK_PARM(r16)(r1)	/* Fetch r7 ret arg */
-	stdx	r7,r0,r0
-	ld	r0,STK_PARM(r17)(r1)	/* Fetch r8 ret arg */
-	stdx	r8,r0,r0
-	ld	r0,STK_PARM(r18)(r1)	/* Fetch r9 ret arg */
-	stdx	r9,r0,r0
-	ld	r0,STK_PARM(r19)(r1)	/* Fetch r10 ret arg */
-	stdx	r10,r0,r0
-	ld	r0,STK_PARM(r20)(r1)	/* Fetch r11 ret arg */
-	stdx	r11,r0,r0
-	ld	r0,STK_PARM(r21)(r1)	/* Fetch r12 ret arg */
-	stdx	r12,r0,r0
+	ld	r12,STK_PARM(r4)(r1)
+	std	r4,  0(r12)
+	std	r5,  8(r12)
+	std	r6, 16(r12)
+	std	r7, 24(r12)
+	std	r8, 32(r12)
+	std	r9, 40(r12)
+	std	r10,48(r12)
+	std	r11,56(r12)
+	std	r12,64(r12)
 
 	lwz	r0,8(r1)
 	mtcrf	0xff,r0
Index: build/arch/powerpc/platforms/pseries/hvconsole.c
===================================================================
--- build.orig/arch/powerpc/platforms/pseries/hvconsole.c	2006-07-18 04:20:13.000000000 +1000
+++ build/arch/powerpc/platforms/pseries/hvconsole.c	2006-07-18 04:24:08.000000000 +1000
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <asm/hvcall.h>
 #include <asm/hvconsole.h>
+#include "plpar_wrappers.h"
 
 /**
  * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
@@ -40,9 +41,9 @@ int hvc_get_chars(uint32_t vtermno, char
 {
 	unsigned long got;
 
-	if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
-		(unsigned long *)buf, (unsigned long *)buf+1) == H_SUCCESS)
+	if (plpar_get_term_char(vtermno, &got, buf) == H_SUCCESS)
 		return got;
+
 	return 0;
 }
 
Index: build/arch/powerpc/platforms/pseries/lpar.c
===================================================================
--- build.orig/arch/powerpc/platforms/pseries/lpar.c	2006-07-18 04:20:13.000000000 +1000
+++ build/arch/powerpc/platforms/pseries/lpar.c	2006-07-18 04:24:08.000000000 +1000
@@ -48,13 +48,11 @@
 #define DBG_LOW(fmt...) do { } while(0)
 #endif
 
-/* in pSeries_hvCall.S */
+/* in hvCall.S */
 EXPORT_SYMBOL(plpar_hcall);
-EXPORT_SYMBOL(plpar_hcall_4out);
+EXPORT_SYMBOL(plpar_hcall9);
 EXPORT_SYMBOL(plpar_hcall_norets);
-EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
-EXPORT_SYMBOL(plpar_hcall_7arg_7ret);
-EXPORT_SYMBOL(plpar_hcall_9arg_9ret);
+
 extern void pSeries_find_serial_port(void);
 
 
@@ -277,7 +275,6 @@ long pSeries_lpar_hpte_insert(unsigned l
 	unsigned long flags;
 	unsigned long slot;
 	unsigned long hpte_v, hpte_r;
-	unsigned long dummy0, dummy1;
 
 	if (!(vflags & HPTE_V_BOLTED))
 		DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
@@ -302,8 +299,7 @@ long pSeries_lpar_hpte_insert(unsigned l
 	if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
 		hpte_r &= ~_PAGE_COHERENT;
 
-	lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
-			      hpte_r, &slot, &dummy0, &dummy1);
+	lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
 	if (unlikely(lpar_rc == H_PTEG_FULL)) {
 		if (!(vflags & HPTE_V_BOLTED))
 			DBG_LOW(" full\n");
Index: build/arch/powerpc/platforms/pseries/plpar_wrappers.h
===================================================================
--- build.orig/arch/powerpc/platforms/pseries/plpar_wrappers.h	2006-07-18 04:20:13.000000000 +1000
+++ build/arch/powerpc/platforms/pseries/plpar_wrappers.h	2006-07-18 04:27:14.000000000 +1000
@@ -5,20 +5,17 @@
 
 static inline long poll_pending(void)
 {
-	unsigned long dummy;
-	return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, &dummy, &dummy, &dummy);
+	return plpar_hcall_norets(H_POLL_PENDING);
 }
 
 static inline long prod_processor(void)
 {
-	plpar_hcall_norets(H_PROD);
-	return 0;
+	return plpar_hcall_norets(H_PROD);
 }
 
 static inline long cede_processor(void)
 {
-	plpar_hcall_norets(H_CEDE);
-	return 0;
+	return plpar_hcall_norets(H_CEDE);
 }
 
 static inline long vpa_call(unsigned long flags, unsigned long cpu,
@@ -42,21 +39,47 @@ static inline long register_vpa(unsigned
 
 extern void vpa_init(int cpu);
 
+static inline long plpar_pte_enter(unsigned long flags,
+		unsigned long hpte_group, unsigned long hpte_v,
+		unsigned long hpte_r, unsigned long *slot)
+{
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall(H_ENTER, retbuf, flags, hpte_group, hpte_v, hpte_r);
+
+	*slot = retbuf[0];
+
+	return rc;
+}
+
 static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex,
 		unsigned long avpn, unsigned long *old_pteh_ret,
 		unsigned long *old_ptel_ret)
 {
-	unsigned long dummy;
-	return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0, old_pteh_ret,
-			old_ptel_ret, &dummy);
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall(H_REMOVE, retbuf, flags, ptex, avpn);
+
+	*old_pteh_ret = retbuf[0];
+	*old_ptel_ret = retbuf[1];
+
+	return rc;
 }
 
 static inline long plpar_pte_read(unsigned long flags, unsigned long ptex,
 		unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
 {
-	unsigned long dummy;
-	return plpar_hcall(H_READ, flags, ptex, 0, 0, old_pteh_ret,
-			old_ptel_ret, &dummy);
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall(H_READ, retbuf, flags, ptex);
+
+	*old_pteh_ret = retbuf[0];
+	*old_ptel_ret = retbuf[1];
+
+	return rc;
 }
 
 static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
@@ -68,9 +91,14 @@ static inline long plpar_pte_protect(uns
 static inline long plpar_tce_get(unsigned long liobn, unsigned long ioba,
 		unsigned long *tce_ret)
 {
-	unsigned long dummy;
-	return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0, tce_ret, &dummy,
-			&dummy);
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall(H_GET_TCE, retbuf, liobn, ioba);
+
+	*tce_ret = retbuf[0];
+
+	return rc;
 }
 
 static inline long plpar_tce_put(unsigned long liobn, unsigned long ioba,
@@ -94,9 +122,17 @@ static inline long plpar_tce_stuff(unsig
 static inline long plpar_get_term_char(unsigned long termno,
 		unsigned long *len_ret, char *buf_ret)
 {
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
 	unsigned long *lbuf = (unsigned long *)buf_ret;	/* TODO: alignment? */
-	return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0, len_ret,
-			lbuf + 0, lbuf + 1);
+
+	rc = plpar_hcall(H_GET_TERM_CHAR, retbuf, termno);
+
+	*len_ret = retbuf[0];
+	lbuf[0] = retbuf[1];
+	lbuf[1] = retbuf[2];
+
+	return rc;
 }
 
 static inline long plpar_put_term_char(unsigned long termno, unsigned long len,
@@ -107,4 +143,31 @@ static inline long plpar_put_term_char(u
 			lbuf[1]);
 }
 
+static inline long plpar_eoi(unsigned long xirr)
+{
+	return plpar_hcall_norets(H_EOI, xirr);
+}
+
+static inline long plpar_cppr(unsigned long cppr)
+{
+	return plpar_hcall_norets(H_CPPR, cppr);
+}
+
+static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr)
+{
+	return plpar_hcall_norets(H_IPI, servernum, mfrr);
+}
+
+static inline long plpar_xirr(unsigned long *xirr_ret)
+{
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall(H_XIRR, retbuf);
+
+	*xirr_ret = retbuf[0];
+
+	return rc;
+}
+
 #endif /* _PSERIES_PLPAR_WRAPPERS_H */
Index: build/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- build.orig/arch/powerpc/platforms/pseries/xics.c	2006-07-18 04:21:59.000000000 +1000
+++ build/arch/powerpc/platforms/pseries/xics.c	2006-07-18 04:25:58.000000000 +1000
@@ -34,6 +34,7 @@
 #include <asm/i8259.h>
 
 #include "xics.h"
+#include "plpar_wrappers.h"
 
 #define XICS_IPI		2
 #define XICS_IRQ_SPURIOUS	0
@@ -110,27 +111,6 @@ static inline void direct_qirr_info(int 
 /* LPAR low level accessors */
 
 
-static inline long plpar_eoi(unsigned long xirr)
-{
-	return plpar_hcall_norets(H_EOI, xirr);
-}
-
-static inline long plpar_cppr(unsigned long cppr)
-{
-	return plpar_hcall_norets(H_CPPR, cppr);
-}
-
-static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr)
-{
-	return plpar_hcall_norets(H_IPI, servernum, mfrr);
-}
-
-static inline long plpar_xirr(unsigned long *xirr_ret)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy);
-}
-
 static inline unsigned int lpar_xirr_info_get(int n_cpu)
 {
 	unsigned long lpar_rc;
Index: build/drivers/net/ibmveth.c
===================================================================
--- build.orig/drivers/net/ibmveth.c	2006-07-18 04:20:13.000000000 +1000
+++ build/drivers/net/ibmveth.c	2006-07-18 04:24:08.000000000 +1000
@@ -702,7 +702,8 @@ static int ibmveth_start_xmit(struct sk_
 					     desc[3].desc,
 					     desc[4].desc,
 					     desc[5].desc,
-					     correlator);
+					     correlator,
+					     &correlator);
 	} while ((lpar_rc == H_BUSY) && (retry_count--));
 
 	if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
Index: build/drivers/net/ibmveth.h
===================================================================
--- build.orig/drivers/net/ibmveth.h	2006-07-18 04:20:13.000000000 +1000
+++ build/drivers/net/ibmveth.h	2006-07-19 06:55:56.000000000 +1000
@@ -61,8 +61,21 @@
 #define h_add_logical_lan_buffer(ua, buf) \
   plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, ua, buf)
 
-#define h_send_logical_lan(ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator) \
-  plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator, &correlator)
+static inline long h_send_logical_lan(unsigned long unit_address,
+		unsigned long desc1, unsigned long desc2, unsigned long desc3,
+		unsigned long desc4, unsigned long desc5, unsigned long desc6,
+		unsigned long corellator_in, unsigned long *corellator_out)
+{
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+
+	rc = plpar_hcall9(H_SEND_LOGICAL_LAN, retbuf, unit_address, desc1,
+			desc2, desc3, desc4, desc5, desc6, corellator_in);
+
+	*corellator_out = retbuf[0];
+
+	return rc;
+}
 
 #define h_multicast_ctrl(ua, cmd, mac) \
   plpar_hcall_norets(H_MULTICAST_CTRL, ua, cmd, mac)
Index: build/include/asm-powerpc/hvcall.h
===================================================================
--- build.orig/include/asm-powerpc/hvcall.h	2006-07-18 04:20:13.000000000 +1000
+++ build/include/asm-powerpc/hvcall.h	2006-07-19 07:16:14.000000000 +1000
@@ -204,94 +204,39 @@
 
 #ifndef __ASSEMBLY__
 
-/* plpar_hcall() -- Generic call interface using above opcodes
+/**
+ * plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments
+ * @opcode: The hypervisor call to make.
  *
- * The actual call interface is a hypervisor call instruction with
- * the opcode in R3 and input args in R4-R7.
- * Status is returned in R3 with variable output values in R4-R11.
- * Only H_PTE_READ with H_READ_4 uses R6-R11 so we ignore it for now
- * and return only two out args which MUST ALWAYS BE PROVIDED.
- */
-long plpar_hcall(unsigned long opcode,
-		 unsigned long arg1,
-		 unsigned long arg2,
-		 unsigned long arg3,
-		 unsigned long arg4,
-		 unsigned long *out1,
-		 unsigned long *out2,
-		 unsigned long *out3);
-
-/* Same as plpar_hcall but for those opcodes that return no values
- * other than status.  Slightly more efficient.
+ * This call supports up to 7 arguments and only returns the status of
+ * the hcall. Use this version where possible, its slightly faster than
+ * the other plpar_hcalls.
  */
 long plpar_hcall_norets(unsigned long opcode, ...);
 
-/*
- * Special hcall interface for ibmveth support.
- * Takes 8 input parms. Returns a rc and stores the
- * R4 return value in *out1.
- */
-long plpar_hcall_8arg_2ret(unsigned long opcode,
-			   unsigned long arg1,
-			   unsigned long arg2,
-			   unsigned long arg3,
-			   unsigned long arg4,
-			   unsigned long arg5,
-			   unsigned long arg6,
-			   unsigned long arg7,
-			   unsigned long arg8,
-			   unsigned long *out1);
-
-/* plpar_hcall_4out()
+/**
+ * plpar_hcall: - Make a pseries hypervisor call
+ * @opcode: The hypervisor call to make.
+ * @retbuf: Buffer to store up to 4 return arguments in.
  *
- * same as plpar_hcall except with 4 output arguments.
+ * This call supports up to 6 arguments and 4 return arguments. Use
+ * PLPAR_HCALL_BUFSIZE to size the return argument buffer.
  *
+ * Used for all but the craziest of phyp interfaces (see plpar_hcall9)
  */
-long plpar_hcall_4out(unsigned long opcode,
-		      unsigned long arg1,
-		      unsigned long arg2,
-		      unsigned long arg3,
-		      unsigned long arg4,
-		      unsigned long *out1,
-		      unsigned long *out2,
-		      unsigned long *out3,
-		      unsigned long *out4);
+#define PLPAR_HCALL_BUFSIZE 4
+long plpar_hcall(unsigned long opcode, unsigned long *retbuf, ...);
 
-long plpar_hcall_7arg_7ret(unsigned long opcode,
-			   unsigned long arg1,
-			   unsigned long arg2,
-			   unsigned long arg3,
-			   unsigned long arg4,
-			   unsigned long arg5,
-			   unsigned long arg6,
-			   unsigned long arg7,
-			   unsigned long *out1,
-			   unsigned long *out2,
-			   unsigned long *out3,
-			   unsigned long *out4,
-			   unsigned long *out5,
-			   unsigned long *out6,
-			   unsigned long *out7);
-
-long plpar_hcall_9arg_9ret(unsigned long opcode,
-			   unsigned long arg1,
-			   unsigned long arg2,
-			   unsigned long arg3,
-			   unsigned long arg4,
-			   unsigned long arg5,
-			   unsigned long arg6,
-			   unsigned long arg7,
-			   unsigned long arg8,
-			   unsigned long arg9,
-			   unsigned long *out1,
-			   unsigned long *out2,
-			   unsigned long *out3,
-			   unsigned long *out4,
-			   unsigned long *out5,
-			   unsigned long *out6,
-			   unsigned long *out7,
-			   unsigned long *out8,
-			   unsigned long *out9);
+/**
+ * plpar_hcall9: - Make a pseries hypervisor call with up to 9 return arguments
+ * @opcode: The hypervisor call to make.
+ * @retbuf: Buffer to store up to 9 return arguments in.
+ *
+ * This call supports up to 9 arguments and 9 return arguments. Use
+ * PLPAR_HCALL9_BUFSIZE to size the return argument buffer.
+ */
+#define PLPAR_HCALL9_BUFSIZE 9
+long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */

^ permalink raw reply

* Re: [PATCH 0/3] powerpc: Instrument Hypervisor Calls
From: Mike Kravetz @ 2006-07-18 21:29 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060718204723.GA6104@w-mikek2.ibm.com>

On Tue, Jul 18, 2006 at 01:47:23PM -0700, Mike Kravetz wrote:
> A small update from the last version.  By popular demand, both
> wall time (mftb) and cpu cycles(PURR) are collected for each call.
> It is interesting to see these two values side by side in the
> output files.

Arnd asked on IRC, so I thought others may be interested in a
sample output file.  Remember, there is one file per CPU. All
values are decimal.  First number is hcall # (in decimal), second
is number of calls, third is total time (mftb) and fourth is cpu
time (PURR).  Note that 'total times' are still in cycles and
can be converted to another format in user space.

[elm3b125]/sys/kernel/debug/hcall_inst >cat cpu0
4 140651 21538230 14456409
8 130064 11855094 9459178
24 14259 1496316 986702
32 1809 354584 315399
84 103 27196 17763
88 1046 108106 109322
100 2596 251229 205154
104 1 1040 1061
108 2208 320491 242708
116 2669 1030894 713272
220 2 532 510
224 130662 47508588184 169383891
228 5 2689902 4622
260 3018 261893 230753

-- 
Mike

^ permalink raw reply

* Re: [PATCH 0/3] powerpc: Instrument Hypervisor Calls
From: Paul Mackerras @ 2006-07-18 21:00 UTC (permalink / raw)
  To: Mike Kravetz; +Cc: linuxppc-dev
In-Reply-To: <20060718204723.GA6104@w-mikek2.ibm.com>

Mike Kravetz writes:

> A small update from the last version.  By popular demand, both
> wall time (mftb) and cpu cycles(PURR) are collected for each call.
> It is interesting to see these two values side by side in the
> output files.

Did you see the patch from Anton that I posted a week or so ago, which
reduces the number of plpar_hcall_* functions?  I'd rather the
instrumentation stuff was based on that.

My other comment is this: wouldn't it actually turn out simpler if we
read the timebase (and PURR, if we really want to do that too) in the
assembly code that implements plpar_hcall_*?

Paul.

^ permalink raw reply

* [PATCH 3/3] powerpc: Instrument Hypervisor Calls: add debugfs files
From: Mike Kravetz @ 2006-07-18 20:50 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060718204723.GA6104@w-mikek2.ibm.com>

Make statistics available via files in debugfs.
--
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>

diff -Naupr linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall_inst.c linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall_inst.c
--- linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall_inst.c	2006-07-18 20:02:21.000000000 +0000
+++ linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall_inst.c	2006-07-18 20:03:32.000000000 +0000
@@ -214,3 +214,96 @@ long plpar_hcall_9arg_9ret(unsigned long
 	update_stats(opcode, t_tb_before, t_cpu_before);
 	return rc;
 }
+
+/*
+ * Routines for displaying the statistics in debugfs
+ */
+static void *hc_start(struct seq_file *m, loff_t *pos)
+{
+	if ((int)*pos < MAX_HCALL_OPCODES)
+		return (void *)(unsigned long)(*pos + 1);
+
+	return NULL;
+}
+
+static void *hc_next(struct seq_file *m, void *p, loff_t * pos)
+{
+	++*pos;
+
+	return hc_start(m, pos);
+}
+
+static void hc_stop(struct seq_file *m, void *p)
+{
+}
+
+static int hc_show(struct seq_file *m, void *p)
+{
+	unsigned long h_num = (unsigned long)p;
+	struct hcall_stats *hs = (struct hcall_stats *)m->private;
+
+	if (hs[h_num].num_calls)
+		seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2,
+			   hs[h_num].num_calls,
+			   hs[h_num].tb_total,
+			   hs[h_num].cpu_total);
+
+	return 0;
+}
+
+static struct seq_operations hcall_inst_seq_ops = {
+        .start = hc_start,
+        .next  = hc_next,
+        .stop  = hc_stop,
+        .show  = hc_show
+};
+
+static int hcall_inst_seq_open(struct inode *inode, struct file *file)
+{
+	int rc;
+	struct seq_file *seq;
+
+	rc = seq_open(file, &hcall_inst_seq_ops);
+	seq = file->private_data;
+	seq->private = file->f_dentry->d_inode->u.generic_ip;
+
+	return rc;
+}
+
+static struct file_operations hcall_inst_seq_fops = {
+	.open = hcall_inst_seq_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+#define	HCALL_ROOT_DIR		"hcall_inst"
+#define CPU_NAME_BUF_SIZE	32
+
+static int __init hcall_inst_init(void)
+{
+	struct dentry *hcall_root;
+	struct dentry *hcall_file;
+	char cpu_name_buf[CPU_NAME_BUF_SIZE];
+	int cpu;
+
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		return 0;
+
+	hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL);
+	if (!hcall_root)
+		return -ENOMEM;
+
+	for_each_cpu(cpu) {
+		snprintf(cpu_name_buf, CPU_NAME_BUF_SIZE, "cpu%d", cpu);
+		hcall_file = debugfs_create_file(cpu_name_buf, S_IRUGO,
+						 hcall_root,
+						 per_cpu(hcall_stats, cpu),
+						 &hcall_inst_seq_fops);
+		if (!hcall_file)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+__initcall(hcall_inst_init);

^ permalink raw reply

* [PATCH 2/3] powerpc: Instrument Hypervisor Calls: add wrappers
From: Mike Kravetz @ 2006-07-18 20:49 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060718204723.GA6104@w-mikek2.ibm.com>

Add wrappers which perform the actual hypervisor call instrumentation.
--
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>

diff -Naupr linux-2.6.17.6/arch/powerpc/Kconfig.debug linux-2.6.17.6.work/arch/powerpc/Kconfig.debug
--- linux-2.6.17.6/arch/powerpc/Kconfig.debug	2006-07-15 19:00:43.000000000 +0000
+++ linux-2.6.17.6.work/arch/powerpc/Kconfig.debug	2006-07-18 19:56:20.000000000 +0000
@@ -18,6 +18,20 @@ config DEBUG_STACK_USAGE
 
 	  This option will slow down process creation somewhat.
 
+config HCALL_STATS
+	bool "Hypervisor call instrumentation"
+	depends on PPC_PSERIES && DEBUG_FS
+	help
+	  Adds code to keep track of the number of hypervisor calls made and
+	  the amount of time spent in hypervisor calls: both wall time (based
+	  on time base) and cpu time (based on PURR).  A directory named
+	  hcall_inst is added at the root of the debugfs filesystem.  Within
+	  the hcall_inst directory are files that contain CPU specific call
+	  statistics.
+
+	  This option will add a small amount of overhead to all hypervisor
+	  calls.
+
 config DEBUGGER
 	bool "Enable debugger hooks"
 	depends on DEBUG_KERNEL
diff -Naupr linux-2.6.17.6/arch/powerpc/platforms/pseries/Makefile linux-2.6.17.6.work/arch/powerpc/platforms/pseries/Makefile
--- linux-2.6.17.6/arch/powerpc/platforms/pseries/Makefile	2006-07-15 19:00:43.000000000 +0000
+++ linux-2.6.17.6.work/arch/powerpc/platforms/pseries/Makefile	2006-07-18 19:56:20.000000000 +0000
@@ -9,3 +9,4 @@ obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o e
 
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
+obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
diff -Naupr linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall.S linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall.S
--- linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall.S	2006-07-15 19:00:43.000000000 +0000
+++ linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall.S	2006-07-18 19:56:20.000000000 +0000
@@ -11,7 +11,35 @@
 #include <asm/hvcall.h>
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
-	
+
+/*
+ * If hcall statistics are desired, all routines are wrapped with code
+ * that does the statistic gathering.
+ */
+#ifndef CONFIG_HCALL_STATS
+#define PLPAR_HCALL		plpar_hcall
+#define PLPAR_HCALL_NORETS	plpar_hcall_norets
+#define PLPAR_HCALL_8ARG_2RET	plpar_hcall_8arg_2ret
+#define PLPAR_HCALL_4OUT	plpar_hcall_4out
+#define PLPAR_HCALL_7ARG_7RET	plpar_hcall_7arg_7ret
+#define PLPAR_HCALL_9ARG_9RET	plpar_hcall_9arg_9ret
+#else
+#define PLPAR_HCALL		plpar_hcall_base
+#define PLPAR_HCALL_NORETS	plpar_hcall_norets_base
+#define PLPAR_HCALL_8ARG_2RET	plpar_hcall_8arg_2ret_base
+#define PLPAR_HCALL_4OUT	plpar_hcall_4out_base
+#define PLPAR_HCALL_7ARG_7RET	plpar_hcall_7arg_7ret_base
+#define PLPAR_HCALL_9ARG_9RET	plpar_hcall_9arg_9ret_base
+
+/*
+ * A special 'indirect' call to a C based wrapper if statistics are desired.
+ * See plpar_hcall_norets_C function header for more details.
+ */
+_GLOBAL(plpar_hcall_norets)
+	b	plpar_hcall_norets_C
+
+#endif
+
 #define STK_PARM(i)     (48 + ((i)-3)*8)
 
 	.text
@@ -25,7 +53,7 @@
 			unsigned long *out2,		R9
 			unsigned long *out3);		R10
  */
-_GLOBAL(plpar_hcall)
+_GLOBAL(PLPAR_HCALL)
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -52,7 +80,7 @@ _GLOBAL(plpar_hcall)
 
 
 /* Simple interface with no output values (other than status) */
-_GLOBAL(plpar_hcall_norets)
+_GLOBAL(PLPAR_HCALL_NORETS)
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -76,7 +104,7 @@ _GLOBAL(plpar_hcall_norets)
 			unsigned long arg8,		112(R1)
 			unsigned long *out1);		120(R1)
  */
-_GLOBAL(plpar_hcall_8arg_2ret)
+_GLOBAL(PLPAR_HCALL_8ARG_2RET)
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -102,7 +130,7 @@ _GLOBAL(plpar_hcall_8arg_2ret)
 		 	unsigned long *out3,		R10
 		 	unsigned long *out4);		112(R1)
  */
-_GLOBAL(plpar_hcall_4out)
+_GLOBAL(PLPAR_HCALL_4OUT)
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -144,7 +172,7 @@ _GLOBAL(plpar_hcall_4out)
 			 unsigned long *out6,		102(R1)
 			 unsigned long *out7);		100(R1)
 */
-_GLOBAL(plpar_hcall_7arg_7ret)
+_GLOBAL(PLPAR_HCALL_7ARG_7RET)
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -193,7 +221,7 @@ _GLOBAL(plpar_hcall_7arg_7ret)
 			 unsigned long *out8,		 94(R1)
 		         unsigned long *out9,            92(R1)
 */
-_GLOBAL(plpar_hcall_9arg_9ret)
+_GLOBAL(PLPAR_HCALL_9ARG_9RET)
 	HMT_MEDIUM
 
 	mfcr	r0
diff -Naupr linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall_inst.c linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall_inst.c
--- linux-2.6.17.6/arch/powerpc/platforms/pseries/hvCall_inst.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17.6.work/arch/powerpc/platforms/pseries/hvCall_inst.c	2006-07-18 19:57:44.000000000 +0000
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2006 Mike Kravetz IBM Corporation
+ *
+ * Hypervisor Call Instrumentation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/cpumask.h>
+#include <asm/hvcall.h>
+#include <asm/firmware.h>
+
+DEFINE_PER_CPU(struct hcall_stats[MAX_HCALL_OPCODES+1], hcall_stats);
+
+/*
+ * Common update of the per-CPU/per-hcall statistics
+ */
+static inline void update_stats(unsigned long opcode,
+				unsigned long t_tb_before,
+				unsigned long t_cpu_before)
+{
+	unsigned long op_index = opcode >> 2;
+	struct hcall_stats *hs = &__get_cpu_var(hcall_stats[op_index]);
+
+	hs->tb_total += (mftb() - t_tb_before);
+	hs->cpu_total += (mfspr(SPRN_PURR) - t_cpu_before);
+	hs->num_calls++;
+}
+
+/*
+ * plpar_hcall wrapper
+ */
+long plpar_hcall(unsigned long opcode,
+                 unsigned long arg1,
+                 unsigned long arg2,
+                 unsigned long arg3,
+                 unsigned long arg4,
+                 unsigned long *out1,
+                 unsigned long *out2,
+                 unsigned long *out3)
+{
+	long rc;
+	unsigned long t_tb_before, t_cpu_before;
+
+	t_tb_before = mftb();
+	t_cpu_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_base(opcode, arg1, arg2, arg3, arg4, out1, out2, out3);
+
+	update_stats(opcode, t_tb_before, t_cpu_before);
+	return rc;
+}
+
+/*
+ * A C based wrapper for plpar_hcall_norets
+ * The wrapper for plpar_hcall_norets is a special case because the function
+ * takes a variable number of arguments.  It is almost impossible to write a
+ * wrapper for a function that takes a variable number of arguments in C.
+ * Therefore, there is an assembly routine in hvCall.S that simply branches
+ * to this C wrapper.  This 'indirection' takes care of the variable arguments
+ * issue.  This C wrapper has a fixed maximum number of arguments.
+ */
+long plpar_hcall_norets_C(unsigned long opcode,
+				unsigned long arg1,
+				unsigned long arg2,
+				unsigned long arg3,
+				unsigned long arg4,
+				unsigned long arg5,
+				unsigned long arg6)
+{
+	long rc;
+	unsigned long t_tb_before, t_cpu_before;
+
+	t_tb_before = mftb();
+	t_cpu_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_norets_base(opcode, arg1, arg2, arg3, arg4, arg5,
+				     arg6);
+
+	update_stats(opcode, t_tb_before, t_cpu_before);
+	return rc;
+}
+
+/*
+ * plpar_hcall_8arg_2ret wrapper
+ */
+long plpar_hcall_8arg_2ret(unsigned long opcode,
+                           unsigned long arg1,
+                           unsigned long arg2,
+                           unsigned long arg3,
+                           unsigned long arg4,
+                           unsigned long arg5,
+                           unsigned long arg6,
+                           unsigned long arg7,
+                           unsigned long arg8,
+                           unsigned long *out1)
+{
+	long rc;
+	unsigned long t_tb_before, t_cpu_before;
+
+	t_tb_before = mftb();
+	t_cpu_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_8arg_2ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
+					arg6, arg7, arg8, out1);
+
+	update_stats(opcode, t_tb_before, t_cpu_before);
+	return rc;
+}
+
+/*
+ * plpar_hcall_4out wrapper
+ */
+long plpar_hcall_4out(unsigned long opcode,
+                      unsigned long arg1,
+                      unsigned long arg2,
+                      unsigned long arg3,
+                      unsigned long arg4,
+                      unsigned long *out1,
+                      unsigned long *out2,
+                      unsigned long *out3,
+                      unsigned long *out4)
+{
+	long rc;
+	unsigned long t_tb_before, t_cpu_before;
+
+	t_tb_before = mftb();
+	t_cpu_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_4out_base(opcode, arg1, arg2, arg3, arg4, out1,
+				   out2, out3, out4);
+
+	update_stats(opcode, t_tb_before, t_cpu_before);
+	return rc;
+}
+
+/*
+ * plpar_hcall_7arg_7ret wrapper
+ */
+long plpar_hcall_7arg_7ret(unsigned long opcode,
+                           unsigned long arg1,
+                           unsigned long arg2,
+                           unsigned long arg3,
+                           unsigned long arg4,
+                           unsigned long arg5,
+                           unsigned long arg6,
+                           unsigned long arg7,
+                           unsigned long *out1,
+                           unsigned long *out2,
+                           unsigned long *out3,
+                           unsigned long *out4,
+                           unsigned long *out5,
+                           unsigned long *out6,
+                           unsigned long *out7)
+{
+	long rc;
+	unsigned long t_tb_before, t_cpu_before;
+
+	t_tb_before = mftb();
+	t_cpu_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_7arg_7ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
+					arg6, arg7, out1, out2, out3, out4,
+					out5, out6, out7);
+
+	update_stats(opcode, t_tb_before, t_cpu_before);
+	return rc;
+}
+
+/*
+ * plpar_hcall_9arg_9ret wrapper
+ */
+long plpar_hcall_9arg_9ret(unsigned long opcode,
+                           unsigned long arg1,
+                           unsigned long arg2,
+                           unsigned long arg3,
+                           unsigned long arg4,
+                           unsigned long arg5,
+                           unsigned long arg6,
+                           unsigned long arg7,
+                           unsigned long arg8,
+                           unsigned long arg9,
+                           unsigned long *out1,
+                           unsigned long *out2,
+                           unsigned long *out3,
+                           unsigned long *out4,
+                           unsigned long *out5,
+                           unsigned long *out6,
+                           unsigned long *out7,
+                           unsigned long *out8,
+                           unsigned long *out9)
+{
+	long rc;
+	unsigned long t_tb_before, t_cpu_before;
+
+	t_tb_before = mftb();
+	t_cpu_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_9arg_9ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
+					arg6, arg7, arg8, arg9, out1, out2,
+					out3, out4, out5, out6, out7, out8,
+					out9);
+
+	update_stats(opcode, t_tb_before, t_cpu_before);
+	return rc;
+}
diff -Naupr linux-2.6.17.6/include/asm-powerpc/hvcall.h linux-2.6.17.6.work/include/asm-powerpc/hvcall.h
--- linux-2.6.17.6/include/asm-powerpc/hvcall.h	2006-07-18 19:35:00.000000000 +0000
+++ linux-2.6.17.6.work/include/asm-powerpc/hvcall.h	2006-07-18 19:56:20.000000000 +0000
@@ -292,6 +292,87 @@ long plpar_hcall_9arg_9ret(unsigned long
 			   unsigned long *out8,
 			   unsigned long *out9);
 
+
+/* For hcall instrumentation.  One structure per-hcall, per-CPU */
+struct hcall_stats {
+	unsigned long	num_calls;	/* number of calls (on this CPU) */
+	unsigned long	tb_total;	/* total wall time (mftb) of calls. */
+	unsigned long	cpu_total;	/* total cpu time (PURR) of calls. */
+};
+
+/* If Hypervisor call instrumentation is enabled, the assembly routine
+ * names are changed from 'plpar_hcall*' to 'plpar_hcall*_base' and
+ * 'plpar_hcall*' routines become instrumented wrappers.  The following
+ * are declarations for the renamed 'plpar_hcall*_base' routines.
+ */
+long plpar_hcall_base (unsigned long opcode,
+		       unsigned long arg1,
+		       unsigned long arg2,
+		       unsigned long arg3,
+		       unsigned long arg4,
+		       unsigned long *out1,
+		       unsigned long *out2,
+		       unsigned long *out3);
+
+long plpar_hcall_norets_base(unsigned long opcode, ...);
+
+long plpar_hcall_8arg_2ret_base(unsigned long opcode,
+				unsigned long arg1,
+				unsigned long arg2,
+				unsigned long arg3,
+				unsigned long arg4,
+				unsigned long arg5,
+				unsigned long arg6,
+				unsigned long arg7,
+				unsigned long arg8,
+				unsigned long *out1);
+
+long plpar_hcall_4out_base(unsigned long opcode,
+			   unsigned long arg1,
+			   unsigned long arg2,
+			   unsigned long arg3,
+			   unsigned long arg4,
+			   unsigned long *out1,
+			   unsigned long *out2,
+			   unsigned long *out3,
+			   unsigned long *out4);
+
+long plpar_hcall_7arg_7ret_base(unsigned long opcode,
+				unsigned long arg1,
+				unsigned long arg2,
+				unsigned long arg3,
+				unsigned long arg4,
+				unsigned long arg5,
+				unsigned long arg6,
+				unsigned long arg7,
+				unsigned long *out1,
+				unsigned long *out2,
+				unsigned long *out3,
+				unsigned long *out4,
+				unsigned long *out5,
+				unsigned long *out6,
+				unsigned long *out7);
+
+long plpar_hcall_9arg_9ret_base(unsigned long opcode,
+				unsigned long arg1,
+				unsigned long arg2,
+				unsigned long arg3,
+				unsigned long arg4,
+				unsigned long arg5,
+				unsigned long arg6,
+				unsigned long arg7,
+				unsigned long arg8,
+				unsigned long arg9,
+				unsigned long *out1,
+				unsigned long *out2,
+				unsigned long *out3,
+				unsigned long *out4,
+				unsigned long *out5,
+				unsigned long *out6,
+				unsigned long *out7,
+				unsigned long *out8,
+				unsigned long *out9);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox