diff --git a/xen/arch/ppc/Kconfig b/xen/arch/ppc/Kconfig index a2ade2ecf4..b32dce39b8 100644 --- a/xen/arch/ppc/Kconfig +++ b/xen/arch/ppc/Kconfig @@ -1,5 +1,6 @@ config PPC def_bool y + select HAS_DEVICE_TREE config PPC64 def_bool y diff --git a/xen/arch/ppc/Makefile b/xen/arch/ppc/Makefile index 098a4dd0a9..0c0a7884a1 100644 --- a/xen/arch/ppc/Makefile +++ b/xen/arch/ppc/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_PPC64) += ppc64/ obj-y += boot-of.init.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.init.o +obj-y += opal.o obj-y += setup.o $(TARGET): $(TARGET)-syms diff --git a/xen/arch/ppc/arch.mk b/xen/arch/ppc/arch.mk index 0183b9ac6a..3bf79bac37 100644 --- a/xen/arch/ppc/arch.mk +++ b/xen/arch/ppc/arch.mk @@ -10,5 +10,4 @@ CFLAGS += -mstrict-align -mcmodel=medium -mabi=elfv2 -fPIC -mno-altivec -mno-vsx LDFLAGS += -m elf64lppc # TODO: Drop override when more of the build is working -override ALL_OBJS-y = arch/$(SRCARCH)/built_in.o -override ALL_LIBS-y = +override ALL_OBJS-y = arch/$(SRCARCH)/built_in.o common/libfdt/built_in.o lib/built_in.o diff --git a/xen/arch/ppc/include/asm/boot.h b/xen/arch/ppc/include/asm/boot.h index 9b8a7c43c2..296539cd9e 100644 --- a/xen/arch/ppc/include/asm/boot.h +++ b/xen/arch/ppc/include/asm/boot.h @@ -4,7 +4,10 @@ #include -/* a collection of interfaces used during boot. */ +/* + * OpenFirmware boot interfaces + */ + enum { OF_FAILURE = -1, OF_SUCCESS = 0, @@ -20,4 +23,15 @@ struct of_service { int enter_of(struct of_service *args, unsigned long entry); void boot_of_init(unsigned long vec); +/* + * OPAL boot interfaces + */ + +struct opal { + uint64_t base; + uint64_t entry; +}; + +void boot_opal_init(const void *fdt); + #endif /* _ASM_PPC_BOOT_H */ diff --git a/xen/arch/ppc/include/asm/bug.h b/xen/arch/ppc/include/asm/bug.h new file mode 100644 index 0000000000..e5e874b31c --- /dev/null +++ b/xen/arch/ppc/include/asm/bug.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ASM_PPC_BUG_H +#define _ASM_PPC_BUG_H + +#include + +/* + * Power ISA guarantees that an instruction consisting of all zeroes is + * illegal. + */ +#define BUG_OPCODE 0x00000000 + +#define BUG_INSTR ".long " __stringify(BUG_OPCODE) + +#define BUG_FN_REG r0 + +#endif /* _ASM_PPC_BUG_H */ diff --git a/xen/arch/ppc/include/asm/cache.h b/xen/arch/ppc/include/asm/cache.h new file mode 100644 index 0000000000..8a0a6b7b17 --- /dev/null +++ b/xen/arch/ppc/include/asm/cache.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ASM_PPC_CACHE_H +#define _ASM_PPC_CACHE_H + +#endif /* _ASM_PPC_CACHE_H */ diff --git a/xen/arch/ppc/include/asm/processor.h b/xen/arch/ppc/include/asm/processor.h index 838d279508..2300640787 100644 --- a/xen/arch/ppc/include/asm/processor.h +++ b/xen/arch/ppc/include/asm/processor.h @@ -133,6 +133,17 @@ struct cpu_user_regs uint32_t entry_vector; }; -#endif +/* + * panic() isn't available at the moment so an infinite loop will be + * used temporarily. + * TODO: change it to panic() + */ +static inline void noreturn die(void) +{ + for ( ; ; ) + HMT_very_low(); +} + +#endif /* __ASSEMBLY__ */ #endif /* _ASM_PPC_PROCESSOR_H */ diff --git a/xen/arch/ppc/include/asm/string.h b/xen/arch/ppc/include/asm/string.h new file mode 100644 index 0000000000..7a420e05e4 --- /dev/null +++ b/xen/arch/ppc/include/asm/string.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ASM_PPC_STRING_H +#define _ASM_PPC_STRING_H + +#endif /* _ASM_PPC_STRING_H */ diff --git a/xen/arch/ppc/include/asm/system.h b/xen/arch/ppc/include/asm/system.h new file mode 100644 index 0000000000..94091df644 --- /dev/null +++ b/xen/arch/ppc/include/asm/system.h @@ -0,0 +1,6 @@ +#ifndef _ASM_SYSTEM_H_ +#define _ASM_SYSTEM_H_ + +#define smp_wmb() __asm__ __volatile__ ( "lwsync" : : : "memory" ) + +#endif /* _ASM_SYSTEM_H */ diff --git a/xen/arch/ppc/opal.c b/xen/arch/ppc/opal.c new file mode 100644 index 0000000000..251de8ac23 --- /dev/null +++ b/xen/arch/ppc/opal.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global OPAL struct containing entrypoint and base */ +struct opal opal; + +void __init boot_opal_init(const void *fdt) +{ + int opal_node; + const __be64 *opal_base; + const __be64 *opal_entry; + + if ( fdt_check_header(fdt) < 0 ) + { + /* + * NOTE: This won't actually print since the early serial + * console isn't set up yet. + */ + early_printk("Booted without valid FDT pointer in r3!\n"); + die(); + } + + opal_node = fdt_path_offset(fdt, "/ibm,opal"); + if ( opal_node < 0 ) + { + early_printk("Unable to find ibm,opal node!\n"); + die(); + } + + opal_base = fdt_getprop(fdt, opal_node, "opal-base-address", NULL); + opal_entry = fdt_getprop(fdt, opal_node, "opal-entry-address", NULL); + if ( !opal_base || !opal_entry ) + { + early_printk("Failed to get opal-base-address/opal-entry-address " + "property from DT!\n"); + die(); + } + + opal.base = be64_to_cpu(*opal_base); + opal.entry = be64_to_cpu(*opal_entry); +} diff --git a/xen/arch/ppc/setup.c b/xen/arch/ppc/setup.c index 7c623a49f5..8ab7bc19ee 100644 --- a/xen/arch/ppc/setup.c +++ b/xen/arch/ppc/setup.c @@ -18,8 +18,13 @@ void __init noreturn start_xen(unsigned long r3, unsigned long r4, } else { - /* kexec boot: Unimplemented */ - __builtin_trap(); + /* + * kexec boot protocol + * + * TODO: This currently assumes an OPAL/PowerNV system, but it's also + * possible to be kexec'd on an OF system. + */ + boot_opal_init((void *)r3); } early_printk("Hello, ppc64le!\n");