aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/opal.h50
-rw-r--r--arch/powerpc/kernel/head_64.S4
-rw-r--r--arch/powerpc/kernel/prom_init.c239
-rw-r--r--arch/powerpc/kernel/prom_init_check.sh3
-rw-r--r--arch/powerpc/platforms/powernv/Makefile2
-rw-r--r--arch/powerpc/platforms/powernv/opal-takeover.S140
6 files changed, 419 insertions, 19 deletions
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
new file mode 100644
index 000000000000..ecdb283f8b7c
--- /dev/null
+++ b/arch/powerpc/include/asm/opal.h
@@ -0,0 +1,50 @@
1/*
2 * PowerNV OPAL definitions.
3 *
4 * Copyright 2011 IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#ifndef __OPAL_H
13#define __OPAL_H
14
15/****** Takeover interface ********/
16
17/* PAPR H-Call used to querty the HAL existence and/or instanciate
18 * it from within pHyp (tech preview only).
19 *
20 * This is exclusively used in prom_init.c
21 */
22
23#ifndef __ASSEMBLY__
24
25struct opal_takeover_args {
26 u64 k_image; /* r4 */
27 u64 k_size; /* r5 */
28 u64 k_entry; /* r6 */
29 u64 k_entry2; /* r7 */
30 u64 hal_addr; /* r8 */
31 u64 rd_image; /* r9 */
32 u64 rd_size; /* r10 */
33 u64 rd_loc; /* r11 */
34};
35
36extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
37
38extern long opal_do_takeover(struct opal_takeover_args *args);
39
40extern int opal_enter_rtas(struct rtas_args *args,
41 unsigned long data,
42 unsigned long entry);
43
44
45#endif /* __ASSEMBLY__ */
46
47/****** OPAL APIs ******/
48
49
50#endif /* __OPAL_H */
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index e708abe576d3..dea8191253d2 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -51,6 +51,10 @@
51 * For pSeries or server processors: 51 * For pSeries or server processors:
52 * 1. The MMU is off & open firmware is running in real mode. 52 * 1. The MMU is off & open firmware is running in real mode.
53 * 2. The kernel is entered at __start 53 * 2. The kernel is entered at __start
54 * -or- For OPAL entry:
55 * 1. The MMU is off, processor in HV mode, primary CPU enters at 0
56 * with device-tree in gpr3
57 * 2. Secondary processors enter at 0x60 with PIR in gpr3
54 * 58 *
55 * For iSeries: 59 * For iSeries:
56 * 1. The MMU is on (as it always is for iSeries) 60 * 1. The MMU is on (as it always is for iSeries)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index a909f4e9343b..9369287aa8c2 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -43,6 +43,7 @@
43#include <asm/btext.h> 43#include <asm/btext.h>
44#include <asm/sections.h> 44#include <asm/sections.h>
45#include <asm/machdep.h> 45#include <asm/machdep.h>
46#include <asm/opal.h>
46 47
47#include <linux/linux_logo.h> 48#include <linux/linux_logo.h>
48 49
@@ -185,6 +186,7 @@ static unsigned long __initdata prom_tce_alloc_end;
185#define PLATFORM_LPAR 0x0001 186#define PLATFORM_LPAR 0x0001
186#define PLATFORM_POWERMAC 0x0400 187#define PLATFORM_POWERMAC 0x0400
187#define PLATFORM_GENERIC 0x0500 188#define PLATFORM_GENERIC 0x0500
189#define PLATFORM_OPAL 0x0600
188 190
189static int __initdata of_platform; 191static int __initdata of_platform;
190 192
@@ -644,7 +646,7 @@ static void __init early_cmdline_parse(void)
644 } 646 }
645} 647}
646 648
647#ifdef CONFIG_PPC_PSERIES 649#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
648/* 650/*
649 * There are two methods for telling firmware what our capabilities are. 651 * There are two methods for telling firmware what our capabilities are.
650 * Newer machines have an "ibm,client-architecture-support" method on the 652 * Newer machines have an "ibm,client-architecture-support" method on the
@@ -1274,6 +1276,195 @@ static void __init prom_init_mem(void)
1274 prom_printf(" ram_top : %x\n", RELOC(ram_top)); 1276 prom_printf(" ram_top : %x\n", RELOC(ram_top));
1275} 1277}
1276 1278
1279static void __init prom_close_stdin(void)
1280{
1281 struct prom_t *_prom = &RELOC(prom);
1282 ihandle val;
1283
1284 if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
1285 call_prom("close", 1, 0, val);
1286}
1287
1288#ifdef CONFIG_PPC_POWERNV
1289
1290static u64 __initdata prom_opal_size;
1291static u64 __initdata prom_opal_align;
1292static int __initdata prom_rtas_start_cpu;
1293static u64 __initdata prom_rtas_data;
1294static u64 __initdata prom_rtas_entry;
1295
1296/* XXX Don't change this structure without updating opal-takeover.S */
1297static struct opal_secondary_data {
1298 s64 ack; /* 0 */
1299 u64 go; /* 8 */
1300 struct opal_takeover_args args; /* 16 */
1301} opal_secondary_data;
1302
1303extern char opal_secondary_entry;
1304
1305static void prom_query_opal(void)
1306{
1307 long rc;
1308
1309 prom_printf("Querying for OPAL presence... ");
1310 rc = opal_query_takeover(&RELOC(prom_opal_size),
1311 &RELOC(prom_opal_align));
1312 prom_debug("(rc = %ld) ", rc);
1313 if (rc != 0) {
1314 prom_printf("not there.\n");
1315 return;
1316 }
1317 RELOC(of_platform) = PLATFORM_OPAL;
1318 prom_printf(" there !\n");
1319 prom_debug(" opal_size = 0x%lx\n", RELOC(prom_opal_size));
1320 prom_debug(" opal_align = 0x%lx\n", RELOC(prom_opal_align));
1321 if (RELOC(prom_opal_align) < 0x10000)
1322 RELOC(prom_opal_align) = 0x10000;
1323}
1324
1325static int prom_rtas_call(int token, int nargs, int nret, int *outputs, ...)
1326{
1327 struct rtas_args rtas_args;
1328 va_list list;
1329 int i;
1330
1331 rtas_args.token = token;
1332 rtas_args.nargs = nargs;
1333 rtas_args.nret = nret;
1334 rtas_args.rets = (rtas_arg_t *)&(rtas_args.args[nargs]);
1335 va_start(list, outputs);
1336 for (i = 0; i < nargs; ++i)
1337 rtas_args.args[i] = va_arg(list, rtas_arg_t);
1338 va_end(list);
1339
1340 for (i = 0; i < nret; ++i)
1341 rtas_args.rets[i] = 0;
1342
1343 opal_enter_rtas(&rtas_args, RELOC(prom_rtas_data),
1344 RELOC(prom_rtas_entry));
1345
1346 if (nret > 1 && outputs != NULL)
1347 for (i = 0; i < nret-1; ++i)
1348 outputs[i] = rtas_args.rets[i+1];
1349 return (nret > 0)? rtas_args.rets[0]: 0;
1350}
1351
1352static void __init prom_opal_hold_cpus(void)
1353{
1354 int i, cnt, cpu, rc;
1355 long j;
1356 phandle node;
1357 char type[64];
1358 u32 servers[8];
1359 struct prom_t *_prom = &RELOC(prom);
1360 void *entry = (unsigned long *)&RELOC(opal_secondary_entry);
1361 struct opal_secondary_data *data = &RELOC(opal_secondary_data);
1362
1363 prom_debug("prom_opal_hold_cpus: start...\n");
1364 prom_debug(" - entry = 0x%x\n", entry);
1365 prom_debug(" - data = 0x%x\n", data);
1366
1367 data->ack = -1;
1368 data->go = 0;
1369
1370 /* look for cpus */
1371 for (node = 0; prom_next_node(&node); ) {
1372 type[0] = 0;
1373 prom_getprop(node, "device_type", type, sizeof(type));
1374 if (strcmp(type, RELOC("cpu")) != 0)
1375 continue;
1376
1377 /* Skip non-configured cpus. */
1378 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
1379 if (strcmp(type, RELOC("okay")) != 0)
1380 continue;
1381
1382 cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
1383 sizeof(servers));
1384 if (cnt == PROM_ERROR)
1385 break;
1386 cnt >>= 2;
1387 for (i = 0; i < cnt; i++) {
1388 cpu = servers[i];
1389 prom_debug("CPU %d ... ", cpu);
1390 if (cpu == _prom->cpu) {
1391 prom_debug("booted !\n");
1392 continue;
1393 }
1394 prom_debug("starting ... ");
1395
1396 /* Init the acknowledge var which will be reset by
1397 * the secondary cpu when it awakens from its OF
1398 * spinloop.
1399 */
1400 data->ack = -1;
1401 rc = prom_rtas_call(RELOC(prom_rtas_start_cpu), 3, 1,
1402 NULL, cpu, entry, data);
1403 prom_debug("rtas rc=%d ...", rc);
1404
1405 for (j = 0; j < 100000000 && data->ack == -1; j++) {
1406 HMT_low();
1407 mb();
1408 }
1409 HMT_medium();
1410 if (data->ack != -1)
1411 prom_debug("done, PIR=0x%x\n", data->ack);
1412 else
1413 prom_debug("timeout !\n");
1414 }
1415 }
1416 prom_debug("prom_opal_hold_cpus: end...\n");
1417}
1418
1419static void prom_opal_takeover(void)
1420{
1421 struct opal_secondary_data *data = &RELOC(opal_secondary_data);
1422 struct opal_takeover_args *args = &data->args;
1423 u64 align = RELOC(prom_opal_align);
1424 u64 top_addr, opal_addr;
1425
1426 args->k_image = (u64)RELOC(_stext);
1427 args->k_size = _end - _stext;
1428 args->k_entry = 0;
1429 args->k_entry2 = 0x60;
1430
1431 top_addr = _ALIGN_UP(args->k_size, align);
1432
1433 if (RELOC(prom_initrd_start) != 0) {
1434 args->rd_image = RELOC(prom_initrd_start);
1435 args->rd_size = RELOC(prom_initrd_end) - args->rd_image;
1436 args->rd_loc = top_addr;
1437 top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
1438 }
1439
1440 /* Pickup an address for the HAL. We want to go really high
1441 * up to avoid problem with future kexecs. On the other hand
1442 * we don't want to be all over the TCEs on P5IOC2 machines
1443 * which are going to be up there too. We assume the machine
1444 * has plenty of memory, and we ask for the HAL for now to
1445 * be just below the 1G point, or above the initrd
1446 */
1447 opal_addr = _ALIGN_DOWN(0x40000000 - RELOC(prom_opal_size), align);
1448 if (opal_addr < top_addr)
1449 opal_addr = top_addr;
1450 args->hal_addr = opal_addr;
1451
1452 prom_debug(" k_image = 0x%lx\n", args->k_image);
1453 prom_debug(" k_size = 0x%lx\n", args->k_size);
1454 prom_debug(" k_entry = 0x%lx\n", args->k_entry);
1455 prom_debug(" k_entry2 = 0x%lx\n", args->k_entry2);
1456 prom_debug(" hal_addr = 0x%lx\n", args->hal_addr);
1457 prom_debug(" rd_image = 0x%lx\n", args->rd_image);
1458 prom_debug(" rd_size = 0x%lx\n", args->rd_size);
1459 prom_debug(" rd_loc = 0x%lx\n", args->rd_loc);
1460 prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
1461 prom_close_stdin();
1462 mb();
1463 data->go = 1;
1464 for (;;)
1465 opal_do_takeover(args);
1466}
1467#endif /* CONFIG_PPC_POWERNV */
1277 1468
1278/* 1469/*
1279 * Allocate room for and instantiate RTAS 1470 * Allocate room for and instantiate RTAS
@@ -1326,6 +1517,12 @@ static void __init prom_instantiate_rtas(void)
1326 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry", 1517 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
1327 &entry, sizeof(entry)); 1518 &entry, sizeof(entry));
1328 1519
1520#ifdef CONFIG_PPC_POWERNV
1521 /* PowerVN takeover hack */
1522 RELOC(prom_rtas_data) = base;
1523 RELOC(prom_rtas_entry) = entry;
1524 prom_getprop(rtas_node, "start-cpu", &RELOC(prom_rtas_start_cpu), 4);
1525#endif
1329 prom_debug("rtas base = 0x%x\n", base); 1526 prom_debug("rtas base = 0x%x\n", base);
1330 prom_debug("rtas entry = 0x%x\n", entry); 1527 prom_debug("rtas entry = 0x%x\n", entry);
1331 prom_debug("rtas size = 0x%x\n", (long)size); 1528 prom_debug("rtas size = 0x%x\n", (long)size);
@@ -1543,7 +1740,7 @@ static void __init prom_hold_cpus(void)
1543 *acknowledge = (unsigned long)-1; 1740 *acknowledge = (unsigned long)-1;
1544 1741
1545 if (reg != _prom->cpu) { 1742 if (reg != _prom->cpu) {
1546 /* Primary Thread of non-boot cpu */ 1743 /* Primary Thread of non-boot cpu or any thread */
1547 prom_printf("starting cpu hw idx %lu... ", reg); 1744 prom_printf("starting cpu hw idx %lu... ", reg);
1548 call_prom("start-cpu", 3, 0, node, 1745 call_prom("start-cpu", 3, 0, node,
1549 secondary_hold, reg); 1746 secondary_hold, reg);
@@ -1652,15 +1849,6 @@ static void __init prom_init_stdout(void)
1652 prom_setprop(val, path, "linux,boot-display", NULL, 0); 1849 prom_setprop(val, path, "linux,boot-display", NULL, 0);
1653} 1850}
1654 1851
1655static void __init prom_close_stdin(void)
1656{
1657 struct prom_t *_prom = &RELOC(prom);
1658 ihandle val;
1659
1660 if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
1661 call_prom("close", 1, 0, val);
1662}
1663
1664static int __init prom_find_machine_type(void) 1852static int __init prom_find_machine_type(void)
1665{ 1853{
1666 struct prom_t *_prom = &RELOC(prom); 1854 struct prom_t *_prom = &RELOC(prom);
@@ -2504,6 +2692,7 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
2504#endif /* CONFIG_BLK_DEV_INITRD */ 2692#endif /* CONFIG_BLK_DEV_INITRD */
2505} 2693}
2506 2694
2695
2507/* 2696/*
2508 * We enter here early on, when the Open Firmware prom is still 2697 * We enter here early on, when the Open Firmware prom is still
2509 * handling exceptions and the MMU hash table for us. 2698 * handling exceptions and the MMU hash table for us.
@@ -2565,7 +2754,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2565 */ 2754 */
2566 prom_check_initrd(r3, r4); 2755 prom_check_initrd(r3, r4);
2567 2756
2568#ifdef CONFIG_PPC_PSERIES 2757#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
2569 /* 2758 /*
2570 * On pSeries, inform the firmware about our capabilities 2759 * On pSeries, inform the firmware about our capabilities
2571 */ 2760 */
@@ -2611,14 +2800,30 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2611#endif 2800#endif
2612 2801
2613 /* 2802 /*
2614 * On non-powermacs, try to instantiate RTAS and puts all CPUs 2803 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
2615 * in spin-loops. PowerMacs don't have a working RTAS and use 2804 * have a usable RTAS implementation.
2616 * a different way to spin CPUs
2617 */ 2805 */
2618 if (RELOC(of_platform) != PLATFORM_POWERMAC) { 2806 if (RELOC(of_platform) != PLATFORM_POWERMAC)
2619 prom_instantiate_rtas(); 2807 prom_instantiate_rtas();
2620 prom_hold_cpus(); 2808
2809#ifdef CONFIG_PPC_POWERNV
2810 /* Detect HAL and try instanciating it & doing takeover */
2811 if (RELOC(of_platform) == PLATFORM_PSERIES_LPAR) {
2812 prom_query_opal();
2813 if (RELOC(of_platform) == PLATFORM_OPAL) {
2814 prom_opal_hold_cpus();
2815 prom_opal_takeover();
2816 }
2621 } 2817 }
2818#endif
2819
2820 /*
2821 * On non-powermacs, put all CPUs in spin-loops.
2822 *
2823 * PowerMacs use a different mechanism to spin CPUs
2824 */
2825 if (RELOC(of_platform) != PLATFORM_POWERMAC)
2826 prom_hold_cpus();
2622 2827
2623 /* 2828 /*
2624 * Fill in some infos for use by the kernel later on 2829 * Fill in some infos for use by the kernel later on
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
index 9f82f4937892..20af6aada517 100644
--- a/arch/powerpc/kernel/prom_init_check.sh
+++ b/arch/powerpc/kernel/prom_init_check.sh
@@ -20,7 +20,8 @@ WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush
20_end enter_prom memcpy memset reloc_offset __secondary_hold 20_end enter_prom memcpy memset reloc_offset __secondary_hold
21__secondary_hold_acknowledge __secondary_hold_spinloop __start 21__secondary_hold_acknowledge __secondary_hold_spinloop __start
22strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224 22strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
23reloc_got2 kernstart_addr memstart_addr linux_banner" 23reloc_got2 kernstart_addr memstart_addr linux_banner _stext
24opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry"
24 25
25NM="$1" 26NM="$1"
26OBJ="$2" 27OBJ="$2"
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index 1c4325056b85..497133027ae5 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -1,2 +1,2 @@
1obj-y += setup.o 1obj-y += setup.o opal-takeover.o
2obj-$(CONFIG_SMP) += smp.o 2obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/powerpc/platforms/powernv/opal-takeover.S b/arch/powerpc/platforms/powernv/opal-takeover.S
new file mode 100644
index 000000000000..77b48b2b9309
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-takeover.S
@@ -0,0 +1,140 @@
1/*
2 * PowerNV OPAL takeover assembly code, for use by prom_init.c
3 *
4 * Copyright 2011 IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <asm/ppc_asm.h>
13#include <asm/hvcall.h>
14#include <asm/asm-offsets.h>
15#include <asm/opal.h>
16
17#define STK_PARAM(i) (48 + ((i)-3)*8)
18
19#define H_HAL_TAKEOVER 0x5124
20#define H_HAL_TAKEOVER_QUERY_MAGIC -1
21
22 .text
23_GLOBAL(opal_query_takeover)
24 mfcr r0
25 stw r0,8(r1)
26 std r3,STK_PARAM(r3)(r1)
27 std r4,STK_PARAM(r4)(r1)
28 li r3,H_HAL_TAKEOVER
29 li r4,H_HAL_TAKEOVER_QUERY_MAGIC
30 HVSC
31 ld r10,STK_PARAM(r3)(r1)
32 std r4,0(r10)
33 ld r10,STK_PARAM(r4)(r1)
34 std r5,0(r10)
35 lwz r0,8(r1)
36 mtcrf 0xff,r0
37 blr
38
39_GLOBAL(opal_do_takeover)
40 mfcr r0
41 stw r0,8(r1)
42 mflr r0
43 std r0,16(r1)
44 bl __opal_do_takeover
45 ld r0,16(r1)
46 mtlr r0
47 lwz r0,8(r1)
48 mtcrf 0xff,r0
49 blr
50
51__opal_do_takeover:
52 ld r4,0(r3)
53 ld r5,0x8(r3)
54 ld r6,0x10(r3)
55 ld r7,0x18(r3)
56 ld r8,0x20(r3)
57 ld r9,0x28(r3)
58 ld r10,0x30(r3)
59 ld r11,0x38(r3)
60 li r3,H_HAL_TAKEOVER
61 HVSC
62 blr
63
64 .globl opal_secondary_entry
65opal_secondary_entry:
66 mr r31,r3
67 mfmsr r11
68 li r12,(MSR_SF | MSR_ISF)@highest
69 sldi r12,r12,48
70 or r11,r11,r12
71 mtmsrd r11
72 isync
73 mfspr r4,SPRN_PIR
74 std r4,0(r3)
751: HMT_LOW
76 ld r4,8(r3)
77 cmpli cr0,r4,0
78 beq 1b
79 HMT_MEDIUM
801: addi r3,r31,16
81 bl __opal_do_takeover
82 b 1b
83
84_GLOBAL(opal_enter_rtas)
85 mflr r0
86 std r0,16(r1)
87 stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
88
89 /* Because PROM is running in 32b mode, it clobbers the high order half
90 * of all registers that it saves. We therefore save those registers
91 * PROM might touch to the stack. (r0, r3-r13 are caller saved)
92 */
93 SAVE_GPR(2, r1)
94 SAVE_GPR(13, r1)
95 SAVE_8GPRS(14, r1)
96 SAVE_10GPRS(22, r1)
97 mfcr r10
98 mfmsr r11
99 std r10,_CCR(r1)
100 std r11,_MSR(r1)
101
102 /* Get the PROM entrypoint */
103 mtlr r5
104
105 /* Switch MSR to 32 bits mode
106 */
107 li r12,1
108 rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
109 andc r11,r11,r12
110 li r12,1
111 rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
112 andc r11,r11,r12
113 mtmsrd r11
114 isync
115
116 /* Enter RTAS here... */
117 blrl
118
119 /* Just make sure that r1 top 32 bits didn't get
120 * corrupt by OF
121 */
122 rldicl r1,r1,0,32
123
124 /* Restore the MSR (back to 64 bits) */
125 ld r0,_MSR(r1)
126 MTMSRD(r0)
127 isync
128
129 /* Restore other registers */
130 REST_GPR(2, r1)
131 REST_GPR(13, r1)
132 REST_8GPRS(14, r1)
133 REST_10GPRS(22, r1)
134 ld r4,_CCR(r1)
135 mtcr r4
136
137 addi r1,r1,PROM_FRAME_SIZE
138 ld r0,16(r1)
139 mtlr r0
140 blr