powerpc/powernv: Remove OPAL v1 takeover
In commit27f4488872
"Add OPAL takeover from PowerVM" we added support for "takeover" on OPAL v1 machines. This was a mode of operation where we would boot under pHyp, and query for the presence of OPAL. If detected we would then do a special sequence to take over the machine, and the kernel would end up running in hypervisor mode. OPAL v1 was never a supported product, and was never shipped outside IBM. As far as we know no one is still using it. Newer versions of OPAL do not use the takeover mechanism. Although the query for OPAL should be harmless on machines with newer OPAL, we have seen a machine where it causes a crash in Open Firmware. The code in early_init_devtree() to copy boot_command_line into cmd_line was added in commit817c21ad9a
"Get kernel command line accross OPAL takeover", and AFAIK is only used by takeover, so should also be removed. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
a1d23d5c94
commit
e2500be2b8
|
@ -303,7 +303,6 @@ config PPC_EARLY_DEBUG_OPAL_VTERMNO
|
|||
This correspond to which /dev/hvcN you want to use for early
|
||||
debug.
|
||||
|
||||
On OPAL v1 (takeover) this should always be 0
|
||||
On OPAL v2, this will be 0 for network console and 1 or 2 for
|
||||
the machine built-in serial ports.
|
||||
|
||||
|
|
|
@ -12,27 +12,7 @@
|
|||
#ifndef __OPAL_H
|
||||
#define __OPAL_H
|
||||
|
||||
/****** Takeover interface ********/
|
||||
|
||||
/* PAPR H-Call used to querty the HAL existence and/or instanciate
|
||||
* it from within pHyp (tech preview only).
|
||||
*
|
||||
* This is exclusively used in prom_init.c
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct opal_takeover_args {
|
||||
u64 k_image; /* r4 */
|
||||
u64 k_size; /* r5 */
|
||||
u64 k_entry; /* r6 */
|
||||
u64 k_entry2; /* r7 */
|
||||
u64 hal_addr; /* r8 */
|
||||
u64 rd_image; /* r9 */
|
||||
u64 rd_size; /* r10 */
|
||||
u64 rd_loc; /* r11 */
|
||||
};
|
||||
|
||||
/*
|
||||
* SG entry
|
||||
*
|
||||
|
@ -55,15 +35,6 @@ struct opal_sg_list {
|
|||
/* We calculate number of sg entries based on PAGE_SIZE */
|
||||
#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
|
||||
|
||||
extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
|
||||
|
||||
extern long opal_do_takeover(struct opal_takeover_args *args);
|
||||
|
||||
struct rtas_args;
|
||||
extern int opal_enter_rtas(struct rtas_args *args,
|
||||
unsigned long data,
|
||||
unsigned long entry);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/****** OPAL APIs ******/
|
||||
|
|
|
@ -662,13 +662,6 @@ void __init early_init_devtree(void *params)
|
|||
of_scan_flat_dt(early_init_dt_scan_fw_dump, NULL);
|
||||
#endif
|
||||
|
||||
/* Pre-initialize the cmd_line with the content of boot_commmand_line,
|
||||
* which will be empty except when the content of the variable has
|
||||
* been overriden by a bootloading mechanism. This happens typically
|
||||
* with HAL takeover
|
||||
*/
|
||||
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
|
||||
|
||||
/* Retrieve various informations from the /chosen node of the
|
||||
* device-tree, including the platform type, initrd location and
|
||||
* size, TCE reserve, and more ...
|
||||
|
|
|
@ -1268,201 +1268,6 @@ static u64 __initdata prom_opal_base;
|
|||
static u64 __initdata prom_opal_entry;
|
||||
#endif
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
/* XXX Don't change this structure without updating opal-takeover.S */
|
||||
static struct opal_secondary_data {
|
||||
s64 ack; /* 0 */
|
||||
u64 go; /* 8 */
|
||||
struct opal_takeover_args args; /* 16 */
|
||||
} opal_secondary_data;
|
||||
|
||||
static u64 __initdata prom_opal_align;
|
||||
static u64 __initdata prom_opal_size;
|
||||
static int __initdata prom_rtas_start_cpu;
|
||||
static u64 __initdata prom_rtas_data;
|
||||
static u64 __initdata prom_rtas_entry;
|
||||
|
||||
extern char opal_secondary_entry;
|
||||
|
||||
static void __init prom_query_opal(void)
|
||||
{
|
||||
long rc;
|
||||
|
||||
/* We must not query for OPAL presence on a machine that
|
||||
* supports TNK takeover (970 blades), as this uses the same
|
||||
* h-call with different arguments and will crash
|
||||
*/
|
||||
if (PHANDLE_VALID(call_prom("finddevice", 1, 1,
|
||||
ADDR("/tnk-memory-map")))) {
|
||||
prom_printf("TNK takeover detected, skipping OPAL check\n");
|
||||
return;
|
||||
}
|
||||
|
||||
prom_printf("Querying for OPAL presence... ");
|
||||
|
||||
rc = opal_query_takeover(&prom_opal_size,
|
||||
&prom_opal_align);
|
||||
prom_debug("(rc = %ld) ", rc);
|
||||
if (rc != 0) {
|
||||
prom_printf("not there.\n");
|
||||
return;
|
||||
}
|
||||
of_platform = PLATFORM_OPAL;
|
||||
prom_printf(" there !\n");
|
||||
prom_debug(" opal_size = 0x%lx\n", prom_opal_size);
|
||||
prom_debug(" opal_align = 0x%lx\n", prom_opal_align);
|
||||
if (prom_opal_align < 0x10000)
|
||||
prom_opal_align = 0x10000;
|
||||
}
|
||||
|
||||
static int __init prom_rtas_call(int token, int nargs, int nret,
|
||||
int *outputs, ...)
|
||||
{
|
||||
struct rtas_args rtas_args;
|
||||
va_list list;
|
||||
int i;
|
||||
|
||||
rtas_args.token = token;
|
||||
rtas_args.nargs = nargs;
|
||||
rtas_args.nret = nret;
|
||||
rtas_args.rets = (rtas_arg_t *)&(rtas_args.args[nargs]);
|
||||
va_start(list, outputs);
|
||||
for (i = 0; i < nargs; ++i)
|
||||
rtas_args.args[i] = va_arg(list, rtas_arg_t);
|
||||
va_end(list);
|
||||
|
||||
for (i = 0; i < nret; ++i)
|
||||
rtas_args.rets[i] = 0;
|
||||
|
||||
opal_enter_rtas(&rtas_args, prom_rtas_data,
|
||||
prom_rtas_entry);
|
||||
|
||||
if (nret > 1 && outputs != NULL)
|
||||
for (i = 0; i < nret-1; ++i)
|
||||
outputs[i] = rtas_args.rets[i+1];
|
||||
return (nret > 0)? rtas_args.rets[0]: 0;
|
||||
}
|
||||
|
||||
static void __init prom_opal_hold_cpus(void)
|
||||
{
|
||||
int i, cnt, cpu, rc;
|
||||
long j;
|
||||
phandle node;
|
||||
char type[64];
|
||||
u32 servers[8];
|
||||
void *entry = (unsigned long *)&opal_secondary_entry;
|
||||
struct opal_secondary_data *data = &opal_secondary_data;
|
||||
|
||||
prom_debug("prom_opal_hold_cpus: start...\n");
|
||||
prom_debug(" - entry = 0x%x\n", entry);
|
||||
prom_debug(" - data = 0x%x\n", data);
|
||||
|
||||
data->ack = -1;
|
||||
data->go = 0;
|
||||
|
||||
/* look for cpus */
|
||||
for (node = 0; prom_next_node(&node); ) {
|
||||
type[0] = 0;
|
||||
prom_getprop(node, "device_type", type, sizeof(type));
|
||||
if (strcmp(type, "cpu") != 0)
|
||||
continue;
|
||||
|
||||
/* Skip non-configured cpus. */
|
||||
if (prom_getprop(node, "status", type, sizeof(type)) > 0)
|
||||
if (strcmp(type, "okay") != 0)
|
||||
continue;
|
||||
|
||||
cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
|
||||
sizeof(servers));
|
||||
if (cnt == PROM_ERROR)
|
||||
break;
|
||||
cnt >>= 2;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
cpu = servers[i];
|
||||
prom_debug("CPU %d ... ", cpu);
|
||||
if (cpu == prom.cpu) {
|
||||
prom_debug("booted !\n");
|
||||
continue;
|
||||
}
|
||||
prom_debug("starting ... ");
|
||||
|
||||
/* Init the acknowledge var which will be reset by
|
||||
* the secondary cpu when it awakens from its OF
|
||||
* spinloop.
|
||||
*/
|
||||
data->ack = -1;
|
||||
rc = prom_rtas_call(prom_rtas_start_cpu, 3, 1,
|
||||
NULL, cpu, entry, data);
|
||||
prom_debug("rtas rc=%d ...", rc);
|
||||
|
||||
for (j = 0; j < 100000000 && data->ack == -1; j++) {
|
||||
HMT_low();
|
||||
mb();
|
||||
}
|
||||
HMT_medium();
|
||||
if (data->ack != -1)
|
||||
prom_debug("done, PIR=0x%x\n", data->ack);
|
||||
else
|
||||
prom_debug("timeout !\n");
|
||||
}
|
||||
}
|
||||
prom_debug("prom_opal_hold_cpus: end...\n");
|
||||
}
|
||||
|
||||
static void __init prom_opal_takeover(void)
|
||||
{
|
||||
struct opal_secondary_data *data = &opal_secondary_data;
|
||||
struct opal_takeover_args *args = &data->args;
|
||||
u64 align = prom_opal_align;
|
||||
u64 top_addr, opal_addr;
|
||||
|
||||
args->k_image = (u64)_stext;
|
||||
args->k_size = _end - _stext;
|
||||
args->k_entry = 0;
|
||||
args->k_entry2 = 0x60;
|
||||
|
||||
top_addr = _ALIGN_UP(args->k_size, align);
|
||||
|
||||
if (prom_initrd_start != 0) {
|
||||
args->rd_image = prom_initrd_start;
|
||||
args->rd_size = prom_initrd_end - args->rd_image;
|
||||
args->rd_loc = top_addr;
|
||||
top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
|
||||
}
|
||||
|
||||
/* Pickup an address for the HAL. We want to go really high
|
||||
* up to avoid problem with future kexecs. On the other hand
|
||||
* we don't want to be all over the TCEs on P5IOC2 machines
|
||||
* which are going to be up there too. We assume the machine
|
||||
* has plenty of memory, and we ask for the HAL for now to
|
||||
* be just below the 1G point, or above the initrd
|
||||
*/
|
||||
opal_addr = _ALIGN_DOWN(0x40000000 - prom_opal_size, align);
|
||||
if (opal_addr < top_addr)
|
||||
opal_addr = top_addr;
|
||||
args->hal_addr = opal_addr;
|
||||
|
||||
/* Copy the command line to the kernel image */
|
||||
strlcpy(boot_command_line, prom_cmd_line,
|
||||
COMMAND_LINE_SIZE);
|
||||
|
||||
prom_debug(" k_image = 0x%lx\n", args->k_image);
|
||||
prom_debug(" k_size = 0x%lx\n", args->k_size);
|
||||
prom_debug(" k_entry = 0x%lx\n", args->k_entry);
|
||||
prom_debug(" k_entry2 = 0x%lx\n", args->k_entry2);
|
||||
prom_debug(" hal_addr = 0x%lx\n", args->hal_addr);
|
||||
prom_debug(" rd_image = 0x%lx\n", args->rd_image);
|
||||
prom_debug(" rd_size = 0x%lx\n", args->rd_size);
|
||||
prom_debug(" rd_loc = 0x%lx\n", args->rd_loc);
|
||||
prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
|
||||
prom_close_stdin();
|
||||
mb();
|
||||
data->go = 1;
|
||||
for (;;)
|
||||
opal_do_takeover(args);
|
||||
}
|
||||
#endif /* __BIG_ENDIAN__ */
|
||||
|
||||
/*
|
||||
* Allocate room for and instantiate OPAL
|
||||
*/
|
||||
|
@ -1597,12 +1402,6 @@ static void __init prom_instantiate_rtas(void)
|
|||
&val, sizeof(val)) != PROM_ERROR)
|
||||
rtas_has_query_cpu_stopped = true;
|
||||
|
||||
#if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__)
|
||||
/* PowerVN takeover hack */
|
||||
prom_rtas_data = base;
|
||||
prom_rtas_entry = entry;
|
||||
prom_getprop(rtas_node, "start-cpu", &prom_rtas_start_cpu, 4);
|
||||
#endif
|
||||
prom_debug("rtas base = 0x%x\n", base);
|
||||
prom_debug("rtas entry = 0x%x\n", entry);
|
||||
prom_debug("rtas size = 0x%x\n", (long)size);
|
||||
|
@ -3027,16 +2826,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
|
|||
prom_instantiate_rtas();
|
||||
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
#ifdef __BIG_ENDIAN__
|
||||
/* Detect HAL and try instanciating it & doing takeover */
|
||||
if (of_platform == PLATFORM_PSERIES_LPAR) {
|
||||
prom_query_opal();
|
||||
if (of_platform == PLATFORM_OPAL) {
|
||||
prom_opal_hold_cpus();
|
||||
prom_opal_takeover();
|
||||
}
|
||||
} else
|
||||
#endif /* __BIG_ENDIAN__ */
|
||||
if (of_platform == PLATFORM_OPAL)
|
||||
prom_instantiate_opal();
|
||||
#endif /* CONFIG_PPC_POWERNV */
|
||||
|
|
|
@ -21,9 +21,7 @@ _end enter_prom memcpy memset reloc_offset __secondary_hold
|
|||
__secondary_hold_acknowledge __secondary_hold_spinloop __start
|
||||
strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
|
||||
reloc_got2 kernstart_addr memstart_addr linux_banner _stext
|
||||
opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry
|
||||
boot_command_line __prom_init_toc_start __prom_init_toc_end
|
||||
btext_setup_display TOC."
|
||||
__prom_init_toc_start __prom_init_toc_end btext_setup_display TOC."
|
||||
|
||||
NM="$1"
|
||||
OBJ="$2"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o
|
||||
obj-y += setup.o opal-wrappers.o opal.o opal-async.o
|
||||
obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
|
||||
obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
|
||||
obj-y += opal-msglog.o
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
* PowerNV OPAL takeover assembly code, for use by prom_init.c
|
||||
*
|
||||
* Copyright 2011 IBM Corp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/opal.h>
|
||||
|
||||
#define H_HAL_TAKEOVER 0x5124
|
||||
#define H_HAL_TAKEOVER_QUERY_MAGIC -1
|
||||
|
||||
.text
|
||||
_GLOBAL(opal_query_takeover)
|
||||
mfcr r0
|
||||
stw r0,8(r1)
|
||||
stdu r1,-STACKFRAMESIZE(r1)
|
||||
std r3,STK_PARAM(R3)(r1)
|
||||
std r4,STK_PARAM(R4)(r1)
|
||||
li r3,H_HAL_TAKEOVER
|
||||
li r4,H_HAL_TAKEOVER_QUERY_MAGIC
|
||||
HVSC
|
||||
addi r1,r1,STACKFRAMESIZE
|
||||
ld r10,STK_PARAM(R3)(r1)
|
||||
std r4,0(r10)
|
||||
ld r10,STK_PARAM(R4)(r1)
|
||||
std r5,0(r10)
|
||||
lwz r0,8(r1)
|
||||
mtcrf 0xff,r0
|
||||
blr
|
||||
|
||||
_GLOBAL(opal_do_takeover)
|
||||
mfcr r0
|
||||
stw r0,8(r1)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
bl __opal_do_takeover
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
lwz r0,8(r1)
|
||||
mtcrf 0xff,r0
|
||||
blr
|
||||
|
||||
__opal_do_takeover:
|
||||
ld r4,0(r3)
|
||||
ld r5,0x8(r3)
|
||||
ld r6,0x10(r3)
|
||||
ld r7,0x18(r3)
|
||||
ld r8,0x20(r3)
|
||||
ld r9,0x28(r3)
|
||||
ld r10,0x30(r3)
|
||||
ld r11,0x38(r3)
|
||||
li r3,H_HAL_TAKEOVER
|
||||
HVSC
|
||||
blr
|
||||
|
||||
.globl opal_secondary_entry
|
||||
opal_secondary_entry:
|
||||
mr r31,r3
|
||||
mfmsr r11
|
||||
li r12,(MSR_SF | MSR_ISF)@highest
|
||||
sldi r12,r12,48
|
||||
or r11,r11,r12
|
||||
mtmsrd r11
|
||||
isync
|
||||
mfspr r4,SPRN_PIR
|
||||
std r4,0(r3)
|
||||
1: HMT_LOW
|
||||
ld r4,8(r3)
|
||||
cmpli cr0,r4,0
|
||||
beq 1b
|
||||
HMT_MEDIUM
|
||||
1: addi r3,r31,16
|
||||
bl __opal_do_takeover
|
||||
b 1b
|
||||
|
||||
_GLOBAL(opal_enter_rtas)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
|
||||
|
||||
/* Because PROM is running in 32b mode, it clobbers the high order half
|
||||
* of all registers that it saves. We therefore save those registers
|
||||
* PROM might touch to the stack. (r0, r3-r13 are caller saved)
|
||||
*/
|
||||
SAVE_GPR(2, r1)
|
||||
SAVE_GPR(13, r1)
|
||||
SAVE_8GPRS(14, r1)
|
||||
SAVE_10GPRS(22, r1)
|
||||
mfcr r10
|
||||
mfmsr r11
|
||||
std r10,_CCR(r1)
|
||||
std r11,_MSR(r1)
|
||||
|
||||
/* Get the PROM entrypoint */
|
||||
mtlr r5
|
||||
|
||||
/* Switch MSR to 32 bits mode
|
||||
*/
|
||||
li r12,1
|
||||
rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
|
||||
andc r11,r11,r12
|
||||
li r12,1
|
||||
rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
|
||||
andc r11,r11,r12
|
||||
mtmsrd r11
|
||||
isync
|
||||
|
||||
/* Enter RTAS here... */
|
||||
blrl
|
||||
|
||||
/* Just make sure that r1 top 32 bits didn't get
|
||||
* corrupt by OF
|
||||
*/
|
||||
rldicl r1,r1,0,32
|
||||
|
||||
/* Restore the MSR (back to 64 bits) */
|
||||
ld r0,_MSR(r1)
|
||||
MTMSRD(r0)
|
||||
isync
|
||||
|
||||
/* Restore other registers */
|
||||
REST_GPR(2, r1)
|
||||
REST_GPR(13, r1)
|
||||
REST_8GPRS(14, r1)
|
||||
REST_10GPRS(22, r1)
|
||||
ld r4,_CCR(r1)
|
||||
mtcr r4
|
||||
|
||||
addi r1,r1,PROM_FRAME_SIZE
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
blr
|
Loading…
Reference in New Issue