Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4aea36b authored by Mohan Kumar M's avatar Mohan Kumar M Committed by Paul Mackerras
Browse files

[POWERPC] Avoid hypervisor statistics calculation in real mode



kexec invokes plpar_hcall hypervisor call in real mode.  plpar_hcall
refers to per cpu variables for accounting hypervisor statistics.
These variables may not be in the RMO region, so accesses to them
in real mode may result in a data storage exception.

This fixes this problem by using a new plpar_hcall_raw function which
does not update the hypervisor call statistics.  Thanks to Anton for
suggesting this idea.

Signed-off-by: default avatarMohan Kumar M <mohan@in.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent f144e7c7
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -123,6 +123,40 @@ _GLOBAL(plpar_hcall)

	blr				/* return r3 = status */

/*
 * plpar_hcall_raw can be called in real mode. kexec/kdump need some
 * hypervisor calls to be executed in real mode. So plpar_hcall_raw
 * does not access the per cpu hypervisor call statistics variables,
 * since these variables may not be present in the RMO region.
 */
_GLOBAL(plpar_hcall_raw)
	HMT_MEDIUM

	mfcr	r0
	stw	r0,8(r1)

	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

	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)
	mtcrf	0xff,r0

	blr				/* return r3 = status */

_GLOBAL(plpar_hcall9)
	HMT_MEDIUM

+1 −1
Original line number Diff line number Diff line
@@ -378,7 +378,7 @@ static void pSeries_lpar_hptab_clear(void)

	/* TODO: Use bulk call */
	for (i = 0; i < hpte_count; i++)
		plpar_pte_remove(0, i, 0, &dummy1, &dummy2);
		plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
}

/*
+16 −0
Original line number Diff line number Diff line
@@ -78,6 +78,22 @@ static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex,
	return rc;
}

/* plpar_pte_remove_raw can be called in real mode. It calls plpar_hcall_raw */
static inline long plpar_pte_remove_raw(unsigned long flags, unsigned long ptex,
		unsigned long avpn, unsigned long *old_pteh_ret,
		unsigned long *old_ptel_ret)
{
	long rc;
	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];

	rc = plpar_hcall_raw(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)
{
+14 −0
Original line number Diff line number Diff line
@@ -236,6 +236,20 @@ long plpar_hcall_norets(unsigned long opcode, ...);
#define PLPAR_HCALL_BUFSIZE 4
long plpar_hcall(unsigned long opcode, unsigned long *retbuf, ...);

/**
 * plpar_hcall_raw: - Make a hypervisor call without calculating hcall stats
 * @opcode: The hypervisor call to make.
 * @retbuf: Buffer to store up to 4 return arguments in.
 *
 * This call supports up to 6 arguments and 4 return arguments. Use
 * PLPAR_HCALL_BUFSIZE to size the return argument buffer.
 *
 * Used when phyp interface needs to be called in real mode. Similar to
 * plpar_hcall, but plpar_hcall_raw works in real mode and does not
 * calculate hypervisor call statistics.
 */
long plpar_hcall_raw(unsigned long opcode, unsigned long *retbuf, ...);

/**
 * plpar_hcall9: - Make a pseries hypervisor call with up to 9 return arguments
 * @opcode: The hypervisor call to make.