Commit 90d5ce82 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

powerpc/pseries: Fix CONFIG_DTL=n build



The recently moved dtl code must be compiled-in if
CONFIG_VIRT_CPU_ACCOUNTING_NATIVE=y even if CONFIG_DTL=n.

Fixes: 6ba5aa54 ("powerpc/pseries: Move dtl scanning and steal time accounting to pseries platform")
Reported-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20221013073131.1485742-1-npiggin@gmail.com
parent a4cb3651
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
			   setup.o iommu.o event_sources.o ras.o \
			   firmware.o power.o dlpar.o mobility.o rng.o \
			   pci.o pci_dlpar.o eeh_pseries.o msi.o \
			   papr_platform_attributes.o
			   papr_platform_attributes.o dtl.o
obj-$(CONFIG_SMP)	+= smp.o
obj-$(CONFIG_KEXEC_CORE)	+= kexec.o
obj-$(CONFIG_PSERIES_ENERGY)	+= pseries_energy.o
@@ -19,7 +19,6 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS)		+= hvcserver.o
obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
obj-$(CONFIG_CMM)		+= cmm.o
obj-$(CONFIG_DTL)		+= dtl.o
obj-$(CONFIG_IO_EVENT_IRQ)	+= io_event_irq.o
obj-$(CONFIG_LPARCFG)		+= lparcfg.o
obj-$(CONFIG_IBMVIO)		+= vio.o
+79 −72
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <asm/plpar_wrappers.h>
#include <asm/machdep.h>

#ifdef CONFIG_DTL
struct dtl {
	struct dtl_entry	*buf;
	int			cpu;
@@ -57,78 +58,6 @@ static DEFINE_PER_CPU(struct dtl_ring, dtl_rings);

static atomic_t dtl_count;

/*
 * Scan the dispatch trace log and count up the stolen time.
 * Should be called with interrupts disabled.
 */
static notrace u64 scan_dispatch_log(u64 stop_tb)
{
	u64 i = local_paca->dtl_ridx;
	struct dtl_entry *dtl = local_paca->dtl_curr;
	struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
	struct lppaca *vpa = local_paca->lppaca_ptr;
	u64 tb_delta;
	u64 stolen = 0;
	u64 dtb;

	if (!dtl)
		return 0;

	if (i == be64_to_cpu(vpa->dtl_idx))
		return 0;
	while (i < be64_to_cpu(vpa->dtl_idx)) {
		dtb = be64_to_cpu(dtl->timebase);
		tb_delta = be32_to_cpu(dtl->enqueue_to_dispatch_time) +
			be32_to_cpu(dtl->ready_to_enqueue_time);
		barrier();
		if (i + N_DISPATCH_LOG < be64_to_cpu(vpa->dtl_idx)) {
			/* buffer has overflowed */
			i = be64_to_cpu(vpa->dtl_idx) - N_DISPATCH_LOG;
			dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
			continue;
		}
		if (dtb > stop_tb)
			break;
		if (dtl_consumer)
			dtl_consumer(dtl, i);
		stolen += tb_delta;
		++i;
		++dtl;
		if (dtl == dtl_end)
			dtl = local_paca->dispatch_log;
	}
	local_paca->dtl_ridx = i;
	local_paca->dtl_curr = dtl;
	return stolen;
}

/*
 * Accumulate stolen time by scanning the dispatch trace log.
 * Called on entry from user mode.
 */
void notrace pseries_accumulate_stolen_time(void)
{
	u64 sst, ust;
	struct cpu_accounting_data *acct = &local_paca->accounting;

	sst = scan_dispatch_log(acct->starttime_user);
	ust = scan_dispatch_log(acct->starttime);
	acct->stime -= sst;
	acct->utime -= ust;
	acct->steal_time += ust + sst;
}

u64 pseries_calculate_stolen_time(u64 stop_tb)
{
	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
		return 0;

	if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx))
		return scan_dispatch_log(stop_tb);

	return 0;
}

/*
 * The cpu accounting code controls the DTL ring buffer, and we get
 * given entries as they are processed.
@@ -436,3 +365,81 @@ static int dtl_init(void)
	return 0;
}
machine_arch_initcall(pseries, dtl_init);
#endif /* CONFIG_DTL */

#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
/*
 * Scan the dispatch trace log and count up the stolen time.
 * Should be called with interrupts disabled.
 */
static notrace u64 scan_dispatch_log(u64 stop_tb)
{
	u64 i = local_paca->dtl_ridx;
	struct dtl_entry *dtl = local_paca->dtl_curr;
	struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
	struct lppaca *vpa = local_paca->lppaca_ptr;
	u64 tb_delta;
	u64 stolen = 0;
	u64 dtb;

	if (!dtl)
		return 0;

	if (i == be64_to_cpu(vpa->dtl_idx))
		return 0;
	while (i < be64_to_cpu(vpa->dtl_idx)) {
		dtb = be64_to_cpu(dtl->timebase);
		tb_delta = be32_to_cpu(dtl->enqueue_to_dispatch_time) +
			be32_to_cpu(dtl->ready_to_enqueue_time);
		barrier();
		if (i + N_DISPATCH_LOG < be64_to_cpu(vpa->dtl_idx)) {
			/* buffer has overflowed */
			i = be64_to_cpu(vpa->dtl_idx) - N_DISPATCH_LOG;
			dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
			continue;
		}
		if (dtb > stop_tb)
			break;
#ifdef CONFIG_DTL
		if (dtl_consumer)
			dtl_consumer(dtl, i);
#endif
		stolen += tb_delta;
		++i;
		++dtl;
		if (dtl == dtl_end)
			dtl = local_paca->dispatch_log;
	}
	local_paca->dtl_ridx = i;
	local_paca->dtl_curr = dtl;
	return stolen;
}

/*
 * Accumulate stolen time by scanning the dispatch trace log.
 * Called on entry from user mode.
 */
void notrace pseries_accumulate_stolen_time(void)
{
	u64 sst, ust;
	struct cpu_accounting_data *acct = &local_paca->accounting;

	sst = scan_dispatch_log(acct->starttime_user);
	ust = scan_dispatch_log(acct->starttime);
	acct->stime -= sst;
	acct->utime -= ust;
	acct->steal_time += ust + sst;
}

u64 pseries_calculate_stolen_time(u64 stop_tb)
{
	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
		return 0;

	if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx))
		return scan_dispatch_log(stop_tb);

	return 0;
}

#endif