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

Commit d3cbff1b authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Michael Ellerman
Browse files

powerpc: Put exception configuration in a common place



The various calls to establish exception endianness and AIL are
now done from a single point using already established CPU and FW
feature bits to decide what to do.

Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 3808a889
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -431,17 +431,6 @@ static inline unsigned long cmo_get_page_size(void)
{
	return CMO_PageSize;
}

extern long pSeries_enable_reloc_on_exc(void);
extern long pSeries_disable_reloc_on_exc(void);

extern long pseries_big_endian_exceptions(void);

#else

#define pSeries_enable_reloc_on_exc()  do {} while (0)
#define pSeries_disable_reloc_on_exc() do {} while (0)

#endif /* CONFIG_PPC_PSERIES */

#endif /* __ASSEMBLY__ */
+1 −0
Original line number Diff line number Diff line
@@ -234,6 +234,7 @@ extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
				   int depth, void *data);
extern int early_init_dt_scan_recoverable_ranges(unsigned long node,
				 const char *uname, int depth, void *data);
extern void opal_configure_cores(void);

extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+12 −0
Original line number Diff line number Diff line
@@ -26,6 +26,18 @@ void initmem_init(void);
void setup_panic(void);
#define ARCH_PANIC_TIMEOUT 180

#ifdef CONFIG_PPC_PSERIES
extern void pseries_enable_reloc_on_exc(void);
extern void pseries_disable_reloc_on_exc(void);
extern void pseries_big_endian_exceptions(void);
extern void pseries_little_endian_exceptions(void);
#else
static inline void pseries_enable_reloc_on_exc(void) {}
static inline void pseries_disable_reloc_on_exc(void) {}
static inline void pseries_big_endian_exceptions(void) {}
static inline void pseries_little_endian_exceptions(void) {}
#endif /* CONFIG_PPC_PSERIES */

#endif /* !__ASSEMBLY__ */

#endif	/* _ASM_POWERPC_SETUP_H */
+42 −14
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@
#include <asm/kvm_ppc.h>
#include <asm/hugetlb.h>
#include <asm/livepatch.h>
#include <asm/opal.h>

#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -205,22 +206,49 @@ static void fixup_boot_paca(void)
	get_paca()->data_offset = 0;
}

static void cpu_ready_for_interrupts(void)
static void configure_exceptions(void)
{
	/* Set IR and DR in PACA MSR */
	get_paca()->kernel_msr = MSR_KERNEL;
	/*
	 * Setup the trampolines from the lowmem exception vectors
	 * to the kdump kernel when not using a relocatable kernel.
	 */
	setup_kdump_trampoline();

	/* Under a PAPR hypervisor, we need hypercalls */
	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
		/* Enable AIL if possible */
		pseries_enable_reloc_on_exc();

		/*
	 * Enable AIL if supported, and we are in hypervisor mode. If we are
	 * not in hypervisor mode, we enable relocation-on interrupts later
	 * in pSeries_setup_arch() using the H_SET_MODE hcall.
		 * Tell the hypervisor that we want our exceptions to
		 * be taken in little endian mode.
		 *
		 * We don't call this for big endian as our calling convention
		 * makes us always enter in BE, and the call may fail under
		 * some circumstances with kdump.
		 */
#ifdef __LITTLE_ENDIAN__
		pseries_little_endian_exceptions();
#endif
	} else {
		/* Set endian mode using OPAL */
		if (firmware_has_feature(FW_FEATURE_OPAL))
			opal_configure_cores();

		/* Enable AIL if supported, and we are in hypervisor mode */
		if (cpu_has_feature(CPU_FTR_HVMODE) &&
		    cpu_has_feature(CPU_FTR_ARCH_207S)) {
			unsigned long lpcr = mfspr(SPRN_LPCR);
			mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3);
		}
	}
}

static void cpu_ready_for_interrupts(void)
{
	/* Set IR and DR in PACA MSR */
	get_paca()->kernel_msr = MSR_KERNEL;
}

/*
 * Early initialization entry point. This is called by head.S
@@ -277,10 +305,10 @@ void __init early_setup(unsigned long dt_ptr)
	probe_machine();

	/*
	 * Setup the trampolines from the lowmem exception vectors
	 * to the kdump kernel when not using a relocatable kernel.
	 * Configure exception handlers. This include setting up trampolines
	 * if needed, setting exception endian mode, etc...
	 */
	setup_kdump_trampoline();
	configure_exceptions();

	/* Initialize the hash table or TLB handling */
	early_init_mmu();
+3 −3
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@
#include <asm/mmu_context.h>
#include <asm/switch_to.h>
#include <asm/firmware.h>
#include <asm/hvcall.h>
#include <asm/setup.h>
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
@@ -1690,7 +1690,7 @@ static int kvmppc_core_init_vm_pr(struct kvm *kvm)
	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
		spin_lock(&kvm_global_user_count_lock);
		if (++kvm_global_user_count == 1)
			pSeries_disable_reloc_on_exc();
			pseries_disable_reloc_on_exc();
		spin_unlock(&kvm_global_user_count_lock);
	}
	return 0;
@@ -1706,7 +1706,7 @@ static void kvmppc_core_destroy_vm_pr(struct kvm *kvm)
		spin_lock(&kvm_global_user_count_lock);
		BUG_ON(kvm_global_user_count == 0);
		if (--kvm_global_user_count == 0)
			pSeries_enable_reloc_on_exc();
			pseries_enable_reloc_on_exc();
		spin_unlock(&kvm_global_user_count_lock);
	}
}
Loading