summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/lib/libhvcall/brokensc1.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/lib/libhvcall/brokensc1.c')
-rw-r--r--qemu/roms/SLOF/lib/libhvcall/brokensc1.c162
1 files changed, 0 insertions, 162 deletions
diff --git a/qemu/roms/SLOF/lib/libhvcall/brokensc1.c b/qemu/roms/SLOF/lib/libhvcall/brokensc1.c
deleted file mode 100644
index e6387e0ab..000000000
--- a/qemu/roms/SLOF/lib/libhvcall/brokensc1.c
+++ /dev/null
@@ -1,162 +0,0 @@
-#include <stdint.h>
-#include <stddef.h>
-#include <cpu.h>
-#include "libhvcall.h"
-#include "byteorder.h"
-
-// #define DEBUG_PATCHERY
-
-#define H_SET_DABR 0x28
-#define INS_SC1 0x44000022
-#define INS_SC1_REPLACE 0x7c000268
-
-extern volatile uint32_t sc1ins;
-
-static unsigned long hcall(uint32_t inst, unsigned long arg0, unsigned long arg1)
-{
- register unsigned long r3 asm("r3") = arg0;
- register unsigned long r4 asm("r4") = arg1;
- register unsigned long r5 asm("r5") = inst;
- asm volatile("bl 1f \n"
- "1: \n"
- "li 11, 2f - 1b \n"
- "mflr 12 \n"
- "add 11, 11, 12 \n"
- "stw 5, 0(11) \n"
- "dcbst 0, 11 \n"
- "sync \n"
- "icbi 0, 11 \n"
- "isync \n"
- "2: \n"
- ".long 0 \n"
- : "=r" (r3)
- : "r" (r3), "r" (r4), "r" (r5)
- : "ctr", "r0", "r6", "r7", "r8", "r9", "r10", "r11",
- "r12", "r13", "r31", "lr", "cc");
- return r3;
-}
-
-static int check_broken_sc1(void)
-{
- long r;
-
- /*
- * Check if we can do a simple hcall. If it works, we are running in
- * a sane environment and everything's fine. If it doesn't, we need
- * to patch the hypercall instruction to something that traps into
- * supervisor mode.
- */
- r = hcall(INS_SC1, H_SET_DABR, 0);
- if (r == H_SUCCESS || r == H_HARDWARE) {
- /* All is fine */
- return 0;
- }
-
- /* We found a broken sc1 host! */
- return 1;
-}
-
-int patch_broken_sc1(void *start, void *end, uint32_t *test_ins)
-{
- uint32_t *p;
- /* The sc 1 instruction */
- uint32_t sc1 = INS_SC1;
- /* An illegal instruction that KVM interprets as sc 1 */
- uint32_t sc1_replacement = INS_SC1_REPLACE;
- int is_le = (test_ins && *test_ins == 0x48000008);
-#ifdef DEBUG_PATCHERY
- int cnt = 0;
-#endif
-
- /* The host is sane, get out of here */
- if (!check_broken_sc1())
- return 0;
-
- /* We only get here with a broken sc1 implementation */
-
- /* Trim the range we scan to not cover the data section */
- if (test_ins) {
- /* This is the cpu table matcher for 970FX */
- uint32_t end_bytes[] = { 0xffff0000, 0x3c0000 };
- /*
- * The .__start symbol contains a trap instruction followed
- * by lots of zeros.
- */
- uint32_t start_bytes[] = { 0x7fe00008, 0, 0, 0, 0 };
-
- if (is_le) {
- end_bytes[0] = bswap_32(end_bytes[0]);
- end_bytes[1] = bswap_32(end_bytes[1]);
- start_bytes[1] = bswap_32(start_bytes[1]);
- }
-
- /* Find the start of the text section */
- for (p = test_ins; (long)p > (long)start; p--) {
- if (p[0] == start_bytes[0] &&
- p[1] == start_bytes[1] &&
- p[2] == start_bytes[2] &&
- p[3] == start_bytes[3] &&
- p[4] == start_bytes[4]) {
- /*
- * We found a match of the instruction sequence
- * trap
- * .long 0
- * .long 0
- * .long 0
- * .long 0
- * which marks the beginning of the .text
- * section on all Linux kernels I've checked.
- */
-#ifdef DEBUG_PATCHERY
- printf("Shortened start from %p to %p\n", end, p);
-#endif
- start = p;
- break;
- }
- }
-
- /* Find the end of the text section */
- for (p = start; (long)p < (long)end; p++) {
- if (p[0] == end_bytes[0] && p[1] == end_bytes[1]) {
- /*
- * We found a match of the PPC970FX entry in the
- * guest kernel's CPU table. That table is
- * usually found early in the .data section and
- * thus marks the end of the .text section for
- * us which we need to patch.
- */
-#ifdef DEBUG_PATCHERY
- printf("Shortened end from %p to %p\n", end, p);
-#endif
- end = p;
- break;
- }
- }
- }
-
- if (is_le) {
- /*
- * The kernel was built for LE mode, so our sc1 and replacement
- * opcodes are in the wrong byte order. Reverse them.
- */
- sc1 = bswap_32(sc1);
- sc1_replacement = bswap_32(sc1_replacement);
- }
-
- /* Patch all sc 1 instructions to reserved instruction 31/308 */
- for (p = start; (long)p < (long)end; p++) {
- if (*p == sc1) {
- *p = sc1_replacement;
- flush_cache(p, sizeof(*p));
-#ifdef DEBUG_PATCHERY
- cnt++;
-#endif
- }
- }
-
-#ifdef DEBUG_PATCHERY
- printf("Patched %d instructions (%p - %p)\n", cnt, start, end);
-#endif
-
- return 1;
-}