From 437fd90c0250dee670290f9b714253671a990160 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Wed, 18 May 2016 13:18:31 +0300 Subject: These changes are the raw update to qemu-2.6. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collission happened in the following patches: migration: do cleanup operation after completion(738df5b9) Bug fix.(1750c932f86) kvmclock: add a new function to update env->tsc.(b52baab2) The code provided by the patches was already in the upstreamed version. Change-Id: I3cc11841a6a76ae20887b2e245710199e1ea7f9a Signed-off-by: José Pekkarinen --- qemu/roms/openbios/arch/ppc/qemu/init.c | 67 ++++++ qemu/roms/openbios/arch/ppc/qemu/methods.c | 36 ++-- qemu/roms/openbios/arch/ppc/qemu/qemu.fs | 45 ++++ qemu/roms/openbios/arch/ppc/qemu/tree.fs | 8 + qemu/roms/openbios/arch/sparc64/call-client.S | 218 +++++-------------- qemu/roms/openbios/arch/sparc64/context.c | 4 + qemu/roms/openbios/arch/sparc64/cpustate.h | 244 +++++++++++++++++++++ qemu/roms/openbios/arch/sparc64/ldscript | 5 + qemu/roms/openbios/arch/sparc64/lib.c | 4 +- qemu/roms/openbios/arch/sparc64/vectors.S | 300 ++++++-------------------- 10 files changed, 507 insertions(+), 424 deletions(-) create mode 100644 qemu/roms/openbios/arch/sparc64/cpustate.h (limited to 'qemu/roms/openbios/arch') diff --git a/qemu/roms/openbios/arch/ppc/qemu/init.c b/qemu/roms/openbios/arch/ppc/qemu/init.c index 4fe8b7220..b76c5706f 100644 --- a/qemu/roms/openbios/arch/ppc/qemu/init.c +++ b/qemu/roms/openbios/arch/ppc/qemu/init.c @@ -302,6 +302,11 @@ cpu_generic_init(const struct cpudef *cpu) fword("encode-string"); push_str("state"); fword("property"); + + PUSH(0x20); + fword("encode-int"); + push_str("reservation-granule-size"); + fword("property"); } static void @@ -596,6 +601,11 @@ go(void) { ucell addr; + /* Insert copyright property for MacOS 9 and below */ + if (find_dev("/rom/macos")) { + fword("insert-copyright-property"); + } + feval("saved-program-state >sps.entry @"); addr = POP(); @@ -680,6 +690,60 @@ static void ffilll(void) } } +/* + * adler32 ( adler buf len -- checksum ) + * + * Adapted from Mark Adler's original implementation (zlib license) + * + * Both OS 9 and BootX require this word for payload validation. + */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +static void adler32(void) +{ + uint32_t len = (uint32_t)POP(); + char *buf = (char *)POP(); + uint32_t adler = (uint32_t)POP(); + + if (buf == NULL) { + RET(-1); + } + + uint32_t base = 65521; + uint32_t nmax = 5552; + + uint32_t s1 = adler & 0xffff; + uint32_t s2 = (adler >> 16) & 0xffff; + + uint32_t k; + while (len > 0) { + k = (len < nmax ? len : nmax); + len -= k; + + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) { + do { + s1 += *buf++; + s2 += s1; + } while (--k); + } + + s1 %= base; + s2 %= base; + } + + RET(s2 << 16 | s1); +} + void arch_of_init(void) { @@ -945,6 +1009,9 @@ arch_of_init(void) /* Implementation of filll word (required by BootX) */ bind_func("filll", ffilll); + + /* Implementation of adler32 word (required by OS 9, BootX) */ + bind_func("(adler32)", adler32); bind_func("platform-boot", boot); bind_func("(go)", go); diff --git a/qemu/roms/openbios/arch/ppc/qemu/methods.c b/qemu/roms/openbios/arch/ppc/qemu/methods.c index fd993daa9..930b47c4e 100644 --- a/qemu/roms/openbios/arch/ppc/qemu/methods.c +++ b/qemu/roms/openbios/arch/ppc/qemu/methods.c @@ -114,6 +114,8 @@ static void ciface_quiesce( unsigned long args[], unsigned long ret[] ) { usb_exit(); + + ob_ide_quiesce(); #if 0 unsigned long msr; /* This seems to be the correct thing to do - but I'm not sure */ @@ -164,21 +166,21 @@ DECLARE_UNNAMED_NODE( mmu, INSTALL_OPEN, 0 ); DECLARE_NODE( mmu_ciface, 0, 0, "+/openprom/client-services" ); -/* ( phys size align --- base ) */ +/* ( [phys] size align --- base ) */ static void mem_claim( void ) { ucell align = POP(); ucell size = POP(); - ucell phys = POP(); - ucell ret = ofmem_claim_phys( phys, size, align ); + phys_addr_t phys = -1; - if( ret == -1 ) { - printk("MEM: claim failure\n"); - throw( -13 ); - return; + if (!align) { + phys = POP(); } - PUSH( ret ); + + phys = ofmem_claim_phys(phys, size, align); + + PUSH(phys); } /* ( phys size --- ) */ @@ -188,24 +190,24 @@ mem_release( void ) POP(); POP(); } -/* ( phys size align --- base ) */ +/* ( [virt] size align --- base ) */ static void mmu_claim( void ) { ucell align = POP(); ucell size = POP(); - ucell phys = POP(); - ucell ret = ofmem_claim_virt( phys, size, align ); + ucell virt = -1; - if( ret == -1 ) { - printk("MMU: CLAIM failure\n"); - throw( -13 ); - return; + if (!align) { + virt = POP(); } - PUSH( ret ); + + virt = ofmem_claim_virt(virt, size, align); + + PUSH(virt); } -/* ( phys size --- ) */ +/* ( virt size --- ) */ static void mmu_release( void ) { diff --git a/qemu/roms/openbios/arch/ppc/qemu/qemu.fs b/qemu/roms/openbios/arch/ppc/qemu/qemu.fs index 458af1bc7..3d99a34a1 100644 --- a/qemu/roms/openbios/arch/ppc/qemu/qemu.fs +++ b/qemu/roms/openbios/arch/ppc/qemu/qemu.fs @@ -93,3 +93,48 @@ variable keyboard-phandle 0 keyboard-phandle ! :noname set-defaults ; PREPOST-initializer + +\ ------------------------------------------------------------------------- +\ copyright property handling +\ ------------------------------------------------------------------------- + +: insert-copyright-property + \ As required for MacOS 9 and below + " Pbclevtug 1983-2001 Nccyr Pbzchgre, Vap. GUVF ZRFFNTR SBE PBZCNGVOVYVGL BAYL" + rot13-str encode-string " copyright" + " /" find-package if + " set-property" $find if + execute + else + 3drop drop + then + then +; + +: delete-copyright-property + \ Remove copyright property created above + active-package + " /" find-package if + active-package! + " copyright" delete-property + then + active-package! +; + +: (exit) + \ Clean up before returning to the interpreter + delete-copyright-property +; + +\ ------------------------------------------------------------------------- +\ Adler-32 wrapper +\ ------------------------------------------------------------------------- + +: adler32 ( adler buf len -- checksum ) + " (adler32)" $find if + execute + else + ." Can't find " ( adler32-name ) type cr + 3drop 0 + then +; diff --git a/qemu/roms/openbios/arch/ppc/qemu/tree.fs b/qemu/roms/openbios/arch/ppc/qemu/tree.fs index 1ed838397..5b6bbc6f7 100644 --- a/qemu/roms/openbios/arch/ppc/qemu/tree.fs +++ b/qemu/roms/openbios/arch/ppc/qemu/tree.fs @@ -42,6 +42,14 @@ new-device : close ; finish-device +new-device + " rom" device-name + h# ff800000 encode-int 0 encode-int encode+ " reg" property + 1 encode-int " #address-cells" property + h# ff800000 encode-int h# 800000 encode-int encode+ + h# ff800000 encode-int encode+ " ranges" property +finish-device + \ ------------------------------------------------------------- \ /packages \ ------------------------------------------------------------- diff --git a/qemu/roms/openbios/arch/sparc64/call-client.S b/qemu/roms/openbios/arch/sparc64/call-client.S index f365e3cb1..a8c0348e4 100644 --- a/qemu/roms/openbios/arch/sparc64/call-client.S +++ b/qemu/roms/openbios/arch/sparc64/call-client.S @@ -1,3 +1,5 @@ +#include "cpustate.h" + .globl sparc64_of_client_interface, client_tba @@ -9,151 +11,9 @@ * behaviour of OBP. */ -#define SAVE_WINDOW_STATE(type) \ - setx client_window, %g6, %g1; \ - rdpr %cwp, %g7; \ - stx %g7, [%g1]; \ - rdpr %cansave, %g7; \ - stx %g7, [%g1 + 0x8]; \ - rdpr %canrestore, %g7; \ - stx %g7, [%g1 + 0x10]; \ - rdpr %otherwin, %g7; \ - stx %g7, [%g1 + 0x18]; \ - rdpr %wstate, %g7; \ - stx %g7, [%g1 + 0x20]; \ - rdpr %cleanwin, %g7; \ - stx %g7, [%g1 + 0x28]; \ - \ - stx %o0, [%g1 + 0x30]; \ - stx %o1, [%g1 + 0x38]; \ - stx %o2, [%g1 + 0x40]; \ - stx %o3, [%g1 + 0x48]; \ - stx %o4, [%g1 + 0x50]; \ - stx %o5, [%g1 + 0x58]; \ - stx %o6, [%g1 + 0x60]; \ - stx %o7, [%g1 + 0x68]; \ - \ - rdpr %pstate, %g7; \ - stx %g7, [%g1 + 0x70]; \ - rd %y, %g7; \ - stx %g7, [%g1 + 0x78]; \ - rd %fprs, %g7; \ - stx %g7, [%g1 + 0x80]; \ - \ - /* Now iterate through all of the windows saving all l and i registers */ \ - add %g1, 0x90, %g5; \ - \ - /* Get the number of windows in %g6 */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - inc %g6; \ - \ -save_cpu_window_##type: \ - deccc %g6; \ - wrpr %g6, %cwp; \ - stx %l0, [%g5]; \ - stx %l1, [%g5 + 0x8]; \ - stx %l2, [%g5 + 0x10]; \ - stx %l3, [%g5 + 0x18]; \ - stx %l4, [%g5 + 0x20]; \ - stx %l5, [%g5 + 0x28]; \ - stx %l6, [%g5 + 0x30]; \ - stx %l7, [%g5 + 0x38]; \ - stx %i0, [%g5 + 0x40]; \ - stx %i1, [%g5 + 0x48]; \ - stx %i2, [%g5 + 0x50]; \ - stx %i3, [%g5 + 0x58]; \ - stx %i4, [%g5 + 0x60]; \ - stx %i5, [%g5 + 0x68]; \ - stx %i6, [%g5 + 0x70]; \ - stx %i7, [%g5 + 0x78]; \ - bne save_cpu_window_##type; \ - add %g5, 0x80, %g5; \ - \ - /* For 8 windows with 16 registers to save in the window, memory required \ - is 16*8*8 = 0x400 bytes */ \ - \ - /* Now we should be in window 0 so update the other window registers */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - dec %g6; \ - wrpr %g6, %cansave; \ - \ - wrpr %g0, %cleanwin; \ - wrpr %g0, %canrestore; \ - wrpr %g0, %otherwin; - - -#define RESTORE_WINDOW_STATE(type) \ - setx client_window, %g6, %g1; \ - \ - /* Get the number of windows in %g6 */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - inc %g6; \ - \ - /* Now iterate through all of the windows restoring all l and i registers */ \ - add %g1, 0x90, %g5; \ - \ -restore_cpu_window_##type: \ - deccc %g6; \ - wrpr %g6, %cwp; \ - ldx [%g5], %l0; \ - ldx [%g5 + 0x8], %l1; \ - ldx [%g5 + 0x10], %l2; \ - ldx [%g5 + 0x18], %l3; \ - ldx [%g5 + 0x20], %l4; \ - ldx [%g5 + 0x28], %l5; \ - ldx [%g5 + 0x30], %l6; \ - ldx [%g5 + 0x38], %l7; \ - ldx [%g5 + 0x40], %i0; \ - ldx [%g5 + 0x48], %i1; \ - ldx [%g5 + 0x50], %i2; \ - ldx [%g5 + 0x58], %i3; \ - ldx [%g5 + 0x60], %i4; \ - ldx [%g5 + 0x68], %i5; \ - ldx [%g5 + 0x70], %i6; \ - ldx [%g5 + 0x78], %i7; \ - bne restore_cpu_window_##type; \ - add %g5, 0x80, %g5; \ - \ - /* Restore the window registers to their original value */ \ - ldx [%g1], %g7; \ - wrpr %g7, %cwp; \ - ldx [%g1 + 0x8], %g7; \ - wrpr %g7, %cansave; \ - ldx [%g1 + 0x10], %g7; \ - wrpr %g7, %canrestore; \ - ldx [%g1 + 0x18], %g7; \ - wrpr %g7, %otherwin; \ - ldx [%g1 + 0x20], %g7; \ - wrpr %g7, %wstate; \ - ldx [%g1 + 0x28], %g7; \ - wrpr %g7, %cleanwin; \ - \ - ldx [%g1 + 0x30], %o0; \ - ldx [%g1 + 0x38], %o1; \ - ldx [%g1 + 0x40], %o2; \ - ldx [%g1 + 0x48], %o3; \ - ldx [%g1 + 0x50], %o4; \ - ldx [%g1 + 0x58], %o5; \ - ldx [%g1 + 0x60], %o6; \ - ldx [%g1 + 0x68], %o7; \ - \ - ldx [%g1 + 0x70], %g7; \ - wrpr %g7, %pstate; \ - ldx [%g1 + 0x78], %g7; \ - wr %g7, 0, %y; \ - ldx [%g1 + 0x80], %g7; \ - wr %g7, 0, %fprs - - .data .align 8 - .skip 16384 -openbios_stack: - client_stack: .xword 0 client_tba: @@ -176,15 +36,15 @@ client_window: sparc64_of_client_interface: /* Save globals on callers stack */ - add %sp, -56, %sp + add %sp, -248, %sp - stx %g1, [%sp + 2047 + 0] - stx %g2, [%sp + 2047 + 8] - stx %g3, [%sp + 2047 + 16] - stx %g4, [%sp + 2047 + 24] - stx %g5, [%sp + 2047 + 32] - stx %g6, [%sp + 2047 + 40] - stx %g7, [%sp + 2047 + 48] + stx %g1, [%sp + 2047 + 192] + stx %g2, [%sp + 2047 + 200] + stx %g3, [%sp + 2047 + 208] + stx %g4, [%sp + 2047 + 216] + stx %g5, [%sp + 2047 + 224] + stx %g6, [%sp + 2047 + 232] + stx %g7, [%sp + 2047 + 240] /* Save client trap table */ setx client_tba, %g6, %g7 @@ -196,22 +56,44 @@ sparc64_of_client_interface: stx %sp, [%g7] /* Save windows */ - SAVE_WINDOW_STATE(cif) - - /* Move to OpenBIOS stack */ - setx openbios_stack - 2047 - 192, %g6, %g7 + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, -CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] + + SAVE_CPU_WINDOW_STATE(cif) + + /* Move to OpenBIOS context stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g6 + setx CONTEXT_STACK_SIZE, %g4, %g5 + sub %g6, %g5, %g6 + stx %g6, [%g7] + + setx - 2047 - 192, %g6, %g7 + add %g1, %g7, %g7 mov %g7, %sp /* Call client inteface */ call of_client_interface ldx [%g1 + 0x30], %o0 - setx client_window, %g6, %g1 - stx %o0, [%g1 + 0x30] - /* Restore windows */ - RESTORE_WINDOW_STATE(cif) - + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + setx CONTEXT_STACK_SIZE, %g4, %g5 + add %g1, %g5, %g1 + stx %g1, [%g7] + + /* Return value */ + stx %o0, [%g1 + 0x30] + + RESTORE_CPU_WINDOW_STATE(cif) + + add %g1, CONTEXT_STATE_SIZE, %g1 + setx _fcstack_ptr, %g6, %g7 + stx %g1, [%g7] + /* Restore stack */ setx client_stack, %g6, %g7 ldx [%g7], %sp @@ -222,15 +104,15 @@ sparc64_of_client_interface: wrpr %g6, %tba /* Restore globals */ - ldx [%sp + 2047 + 0], %g1 - ldx [%sp + 2047 + 8], %g2 - ldx [%sp + 2047 + 16], %g3 - ldx [%sp + 2047 + 24], %g4 - ldx [%sp + 2047 + 32], %g5 - ldx [%sp + 2047 + 40], %g6 - ldx [%sp + 2047 + 48], %g7 - - add %sp, 56, %sp + ldx [%sp + 2047 + 192], %g1 + ldx [%sp + 2047 + 200], %g2 + ldx [%sp + 2047 + 208], %g3 + ldx [%sp + 2047 + 216], %g4 + ldx [%sp + 2047 + 224], %g5 + ldx [%sp + 2047 + 232], %g6 + ldx [%sp + 2047 + 240], %g7 + + add %sp, 248, %sp jmp %o7+8 nop diff --git a/qemu/roms/openbios/arch/sparc64/context.c b/qemu/roms/openbios/arch/sparc64/context.c index 2e7668958..98932ee9c 100644 --- a/qemu/roms/openbios/arch/sparc64/context.c +++ b/qemu/roms/openbios/arch/sparc64/context.c @@ -40,6 +40,10 @@ static uint8_t image_stack[IMAGE_STACK_SIZE]; /* Pointer to startup context (physical address) */ unsigned long __boot_ctx; +/* Pointer to Forth context stack */ +void *_fcstack_ptr = &_efcstack; + + /* * Main starter * This is the C function that runs first. diff --git a/qemu/roms/openbios/arch/sparc64/cpustate.h b/qemu/roms/openbios/arch/sparc64/cpustate.h new file mode 100644 index 000000000..0c276bfd1 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/cpustate.h @@ -0,0 +1,244 @@ +/* + * Save/restore CPU state macros + * + * Copyright (C) 2015 Mark Cave-Ayland (mark.cave-ayland@ilande.co.uk>) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +/* State size for context (see below) */ +#define CONTEXT_STATE_SIZE 0x510 + +/* Stack size for context (allocated inline of the context stack) */ +#define CONTEXT_STACK_SIZE 0x2000 + +/* + * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch + * to C to occur within the MMU I/D TLB miss handlers. + * + * Because these handlers are called on a TLB miss, we cannot use flushw to store + * processor window state on the stack, as the memory areas used by each window's + * stack pointer may not be in the TLB, causing recursive TLB miss traps. + * + * For this reason, we save window state by manually rotating the window registers + * and saving their contents (along with other vital registers) into a special + * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and + * so won't cause issues with trap recursion. + * + * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow + * window fill/spill traps if required), switch to our safe tlb_handler_stack and + * invoke the miss handler. + */ + +#define SAVE_CPU_WINDOW_STATE(type) \ + /* Save window state into context at %g1 */ \ + rdpr %cwp, %g7; \ + stx %g7, [%g1]; \ + rdpr %cansave, %g7; \ + stx %g7, [%g1 + 0x8]; \ + rdpr %canrestore, %g7; \ + stx %g7, [%g1 + 0x10]; \ + rdpr %otherwin, %g7; \ + stx %g7, [%g1 + 0x18]; \ + rdpr %wstate, %g7; \ + stx %g7, [%g1 + 0x20]; \ + rdpr %cleanwin, %g7; \ + stx %g7, [%g1 + 0x28]; \ + \ + stx %o0, [%g1 + 0x30]; \ + stx %o1, [%g1 + 0x38]; \ + stx %o2, [%g1 + 0x40]; \ + stx %o3, [%g1 + 0x48]; \ + stx %o4, [%g1 + 0x50]; \ + stx %o5, [%g1 + 0x58]; \ + stx %o6, [%g1 + 0x60]; \ + stx %o7, [%g1 + 0x68]; \ + \ + rdpr %pstate, %g7; \ + stx %g7, [%g1 + 0x70]; \ + rd %y, %g7; \ + stx %g7, [%g1 + 0x78]; \ + rd %fprs, %g7; \ + stx %g7, [%g1 + 0x80]; \ + rdpr %tl, %g7; \ + stx %g7, [%g1 + 0x88]; \ + \ + /* Now iterate through all of the windows saving all l and i registers */ \ + add %g1, 0x90, %g5; \ + \ + /* Get the number of windows in %g6 */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + \ + mov %g6, %g4; \ + inc %g4; \ + \ + /* Starting cwp in g7 */ \ + rdpr %cwp, %g7; \ + \ +save_cpu_window_##type: \ + wrpr %g7, %cwp; \ + stx %l0, [%g5]; \ + stx %l1, [%g5 + 0x8]; \ + stx %l2, [%g5 + 0x10]; \ + stx %l3, [%g5 + 0x18]; \ + stx %l4, [%g5 + 0x20]; \ + stx %l5, [%g5 + 0x28]; \ + stx %l6, [%g5 + 0x30]; \ + stx %l7, [%g5 + 0x38]; \ + stx %i0, [%g5 + 0x40]; \ + stx %i1, [%g5 + 0x48]; \ + stx %i2, [%g5 + 0x50]; \ + stx %i3, [%g5 + 0x58]; \ + stx %i4, [%g5 + 0x60]; \ + stx %i5, [%g5 + 0x68]; \ + stx %i6, [%g5 + 0x70]; \ + stx %i7, [%g5 + 0x78]; \ + dec %g7; \ + and %g7, %g6, %g7; \ + subcc %g4, 1, %g4; \ + bne save_cpu_window_##type; \ + add %g5, 0x80, %g5; \ + \ + /* For 8 windows with 16 registers to save in the window, memory required \ + is 16*8*8 = 0x400 bytes */ \ + \ + /* Now we should be in window 0 so update the other window registers */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + dec %g6; \ + wrpr %g6, %cansave; \ + \ + wrpr %g0, %cleanwin; \ + wrpr %g0, %canrestore; \ + wrpr %g0, %otherwin; \ + + +#define SAVE_CPU_TRAP_STATE(type) \ + /* Save trap state into context at %g1 */ \ + add %g1, 0x490, %g5; \ + mov 4, %g6; \ + \ +save_trap_state_##type: \ + deccc %g6; \ + wrpr %g6, %tl; \ + rdpr %tpc, %g7; \ + stx %g7, [%g5]; \ + rdpr %tnpc, %g7; \ + stx %g7, [%g5 + 0x8]; \ + rdpr %tstate, %g7; \ + stx %g7, [%g5 + 0x10]; \ + rdpr %tt, %g7; \ + stx %g7, [%g5 + 0x18]; \ + bne save_trap_state_##type; \ + add %g5, 0x20, %g5; \ + \ + /* For 4 trap levels with 4 registers, memory required is \ + 4*8*4 = 0x80 bytes */ + +/* Save all state into context at %g1 */ +#define SAVE_CPU_STATE(type) \ + SAVE_CPU_WINDOW_STATE(type); \ + SAVE_CPU_TRAP_STATE(type); + + +#define RESTORE_CPU_WINDOW_STATE(type) \ + /* Restore window state from context at %g1 */ \ + \ + /* Get the number of windows in %g6 */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + \ + mov %g6, %g4; \ + inc %g4; \ + \ + /* Set starting window */ \ + ldx [%g1], %g7; \ + \ + /* Now iterate through all of the windows restoring all l and i registers */ \ + add %g1, 0x90, %g5; \ + \ +restore_cpu_window_##type: \ + wrpr %g7, %cwp; \ + ldx [%g5], %l0; \ + ldx [%g5 + 0x8], %l1; \ + ldx [%g5 + 0x10], %l2; \ + ldx [%g5 + 0x18], %l3; \ + ldx [%g5 + 0x20], %l4; \ + ldx [%g5 + 0x28], %l5; \ + ldx [%g5 + 0x30], %l6; \ + ldx [%g5 + 0x38], %l7; \ + ldx [%g5 + 0x40], %i0; \ + ldx [%g5 + 0x48], %i1; \ + ldx [%g5 + 0x50], %i2; \ + ldx [%g5 + 0x58], %i3; \ + ldx [%g5 + 0x60], %i4; \ + ldx [%g5 + 0x68], %i5; \ + ldx [%g5 + 0x70], %i6; \ + ldx [%g5 + 0x78], %i7; \ + dec %g7; \ + and %g7, %g6, %g7; \ + subcc %g4, 1, %g4; \ + bne restore_cpu_window_##type; \ + add %g5, 0x80, %g5; \ + \ + /* Restore the window registers to their original value */ \ + ldx [%g1], %g7; \ + wrpr %g7, %cwp; \ + ldx [%g1 + 0x8], %g7; \ + wrpr %g7, %cansave; \ + ldx [%g1 + 0x10], %g7; \ + wrpr %g7, %canrestore; \ + ldx [%g1 + 0x18], %g7; \ + wrpr %g7, %otherwin; \ + ldx [%g1 + 0x20], %g7; \ + wrpr %g7, %wstate; \ + ldx [%g1 + 0x28], %g7; \ + wrpr %g7, %cleanwin; \ + \ + ldx [%g1 + 0x30], %o0; \ + ldx [%g1 + 0x38], %o1; \ + ldx [%g1 + 0x40], %o2; \ + ldx [%g1 + 0x48], %o3; \ + ldx [%g1 + 0x50], %o4; \ + ldx [%g1 + 0x58], %o5; \ + ldx [%g1 + 0x60], %o6; \ + ldx [%g1 + 0x68], %o7; \ + \ + ldx [%g1 + 0x70], %g7; \ + wrpr %g7, %pstate; \ + ldx [%g1 + 0x78], %g7; \ + wr %g7, 0, %y; \ + ldx [%g1 + 0x80], %g7; \ + wr %g7, 0, %fprs; \ + + +#define RESTORE_CPU_TRAP_STATE(type) \ + /* Restore trap state from context at %g1 */ \ + add %g1, 0x490, %g5; \ + mov 4, %g6; \ + \ +restore_trap_state_##type: \ + deccc %g6; \ + wrpr %g6, %tl; \ + ldx [%g5], %g7; \ + wrpr %g7, %tpc; \ + ldx [%g5 + 0x8], %g7; \ + wrpr %g7, %tnpc; \ + ldx [%g5 + 0x10], %g7; \ + wrpr %g7, %tstate; \ + ldx [%g5 + 0x18], %g7; \ + wrpr %g7, %tt; \ + bne restore_trap_state_##type; \ + add %g5, 0x20, %g5; \ + \ + ldx [%g1 + 0x88], %g7; \ + wrpr %g7, %tl + +/* Restore all state from context at %g1 */ +#define RESTORE_CPU_STATE(type) \ + RESTORE_CPU_WINDOW_STATE(type); \ + RESTORE_CPU_TRAP_STATE(type); diff --git a/qemu/roms/openbios/arch/sparc64/ldscript b/qemu/roms/openbios/arch/sparc64/ldscript index 54288e825..c5cc6a5ce 100644 --- a/qemu/roms/openbios/arch/sparc64/ldscript +++ b/qemu/roms/openbios/arch/sparc64/ldscript @@ -50,6 +50,11 @@ SECTIONS *(.bss.*) *(COMMON) + _fcstack = .; + . += 32768; + . = ALIGN(16); + _efcstack = .; + _stack = .; . += STACK_SIZE; . = ALIGN(16); diff --git a/qemu/roms/openbios/arch/sparc64/lib.c b/qemu/roms/openbios/arch/sparc64/lib.c index e9101af52..4709ca8fe 100644 --- a/qemu/roms/openbios/arch/sparc64/lib.c +++ b/qemu/roms/openbios/arch/sparc64/lib.c @@ -458,10 +458,10 @@ NODE_METHODS(mmu) = { void ob_mmu_init(const char *cpuname, uint64_t ram_size) { /* memory node */ - REGISTER_NODE_METHODS(memory, "/memory"); + REGISTER_NODE(memory); /* MMU node */ - REGISTER_NODE_METHODS(mmu, "/virtual-memory"); + REGISTER_NODE(mmu); ofmem_register(find_dev("/memory"), find_dev("/virtual-memory")); diff --git a/qemu/roms/openbios/arch/sparc64/vectors.S b/qemu/roms/openbios/arch/sparc64/vectors.S index 927c1cdc7..9d86b6bd8 100644 --- a/qemu/roms/openbios/arch/sparc64/vectors.S +++ b/qemu/roms/openbios/arch/sparc64/vectors.S @@ -24,6 +24,7 @@ */ #define __ASSEMBLY__ +#include "cpustate.h" #include "pstate.h" #include #define ASI_BP ASI_PHYS_BYPASS_EC_E @@ -276,17 +277,8 @@ tl1_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8) .section ".data" .align 8 - .globl tlb_handler_stack_top, tlb_handler_stack_pointer, obp_ticks_pointer + .globl obp_ticks_pointer - ! Stack for the tlb MMU trap handlers -tlb_handler_stack_bottom: - .skip 8192 -tlb_handler_stack_top: - .skip 8 - - ! MMU trap handler stack pointer -tlb_handler_stack_pointer: - .xword tlb_handler_stack_top ! Pointer to current tick value obp_ticks_pointer: @@ -336,234 +328,30 @@ fill_32bit: restored retry -/* - * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch - * to C to occur within the MMU I/D TLB miss handlers. - * - * Because these handlers are called on a TLB miss, we cannot use flushw to store - * processor window state on the stack, as the memory areas used by each window's - * stack pointer may not be in the TLB, causing recursive TLB miss traps. - * - * For this reason, we save window state by manually rotating the window registers - * and saving their contents (along with other vital registers) into a special - * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and - * so won't cause issues with trap recursion. - * - * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow - * window fill/spill traps if required), switch to our safe tlb_handler_stack and - * invoke the miss handler. - */ - -#define SAVE_CPU_STATE(type) \ - /* Set up our exception stack pointer in %g1 */ \ - setx tlb_handler_stack_pointer, %g7, %g6; \ - ldx [%g6], %g1; \ - add %g1, -0x510, %g1; \ - \ - /* First save the various state registers */ \ - rdpr %cwp, %g7; \ - stx %g7, [%g1]; \ - rdpr %cansave, %g7; \ - stx %g7, [%g1 + 0x8]; \ - rdpr %canrestore, %g7; \ - stx %g7, [%g1 + 0x10]; \ - rdpr %otherwin, %g7; \ - stx %g7, [%g1 + 0x18]; \ - rdpr %wstate, %g7; \ - stx %g7, [%g1 + 0x20]; \ - rdpr %cleanwin, %g7; \ - stx %g7, [%g1 + 0x28]; \ - rdpr %pstate, %g7; \ - stx %g7, [%g1 + 0x30]; \ - \ - rd %y, %g7; \ - stx %g7, [%g1 + 0x38]; \ - rd %fprs, %g7; \ - stx %g7, [%g1 + 0x40]; \ - \ - rdpr %tl, %g7; \ - stx %g7, [%g1 + 0x48]; \ - \ - /* Trap state */ \ - add %g1, 0x50, %g5; \ - mov 4, %g6; \ - \ -save_trap_state_##type: \ - deccc %g6; \ - wrpr %g6, %tl; \ - rdpr %tpc, %g7; \ - stx %g7, [%g5]; \ - rdpr %tnpc, %g7; \ - stx %g7, [%g5 + 0x8]; \ - rdpr %tstate, %g7; \ - stx %g7, [%g5 + 0x10]; \ - rdpr %tt, %g7; \ - stx %g7, [%g5 + 0x18]; \ - bne save_trap_state_##type; \ - add %g5, 0x20, %g5; \ - \ - /* For 4 trap levels with 4 registers, memory required is - 4*8*4 = 0x80 bytes */ \ - \ - /* Save the o registers */ \ - stx %o0, [%g1 + 0xd0]; \ - stx %o1, [%g1 + 0xd8]; \ - stx %o2, [%g1 + 0xe0]; \ - stx %o3, [%g1 + 0xe8]; \ - stx %o4, [%g1 + 0xf0]; \ - stx %o5, [%g1 + 0xf8]; \ - stx %o6, [%g1 + 0x100]; \ - stx %o7, [%g1 + 0x108]; \ - \ - /* Now iterate through all of the windows saving all l and i registers */ \ - add %g1, 0x110, %g5; \ - \ - /* Get the number of windows in %g6 */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - inc %g6; \ - \ -save_cpu_window_##type: \ - deccc %g6; \ - wrpr %g6, %cwp; \ - stx %l0, [%g5]; \ - stx %l1, [%g5 + 0x8]; \ - stx %l2, [%g5 + 0x10]; \ - stx %l3, [%g5 + 0x18]; \ - stx %l4, [%g5 + 0x20]; \ - stx %l5, [%g5 + 0x28]; \ - stx %l6, [%g5 + 0x30]; \ - stx %l7, [%g5 + 0x38]; \ - stx %i0, [%g5 + 0x40]; \ - stx %i1, [%g5 + 0x48]; \ - stx %i2, [%g5 + 0x50]; \ - stx %i3, [%g5 + 0x58]; \ - stx %i4, [%g5 + 0x60]; \ - stx %i5, [%g5 + 0x68]; \ - stx %i6, [%g5 + 0x70]; \ - stx %i7, [%g5 + 0x78]; \ - bne save_cpu_window_##type; \ - add %g5, 0x80, %g5; \ - \ - /* For 8 windows with 16 registers to save in the window, memory required - is 16*8*8 = 0x400 bytes */ \ - \ - /* Now we should be in window 0 so update the other window registers */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - dec %g6; \ - wrpr %g6, %cansave; \ - \ - wrpr %g0, %cleanwin; \ - wrpr %g0, %canrestore; \ - wrpr %g0, %otherwin; \ - \ - /* Update our exception stack pointer */ \ - setx tlb_handler_stack_pointer, %g7, %g6; \ - stx %g1, [%g6]; - - -#define RESTORE_CPU_STATE(type) \ - /* Set up our exception stack pointer in %g1 */ \ - setx tlb_handler_stack_pointer, %g7, %g6; \ - ldx [%g6], %g1; \ - \ - /* Get the number of windows in %g6 */ \ - rdpr %ver, %g6; \ - and %g6, 0xf, %g6; \ - inc %g6; \ - \ - /* Now iterate through all of the windows restoring all l and i registers */ \ - add %g1, 0x110, %g5; \ - \ -restore_cpu_window_##type: \ - deccc %g6; \ - wrpr %g6, %cwp; \ - ldx [%g5], %l0; \ - ldx [%g5 + 0x8], %l1; \ - ldx [%g5 + 0x10], %l2; \ - ldx [%g5 + 0x18], %l3; \ - ldx [%g5 + 0x20], %l4; \ - ldx [%g5 + 0x28], %l5; \ - ldx [%g5 + 0x30], %l6; \ - ldx [%g5 + 0x38], %l7; \ - ldx [%g5 + 0x40], %i0; \ - ldx [%g5 + 0x48], %i1; \ - ldx [%g5 + 0x50], %i2; \ - ldx [%g5 + 0x58], %i3; \ - ldx [%g5 + 0x60], %i4; \ - ldx [%g5 + 0x68], %i5; \ - ldx [%g5 + 0x70], %i6; \ - ldx [%g5 + 0x78], %i7; \ - bne restore_cpu_window_##type; \ - add %g5, 0x80, %g5; \ - \ - /* Restore the window registers to their original value */ \ - ldx [%g1], %g7; \ - wrpr %g7, %cwp; \ - ldx [%g1 + 0x8], %g7; \ - wrpr %g7, %cansave; \ - ldx [%g1 + 0x10], %g7; \ - wrpr %g7, %canrestore; \ - ldx [%g1 + 0x18], %g7; \ - wrpr %g7, %otherwin; \ - ldx [%g1 + 0x20], %g7; \ - wrpr %g7, %wstate; \ - ldx [%g1 + 0x28], %g7; \ - wrpr %g7, %cleanwin; \ - ldx [%g1 + 0x30], %g7; \ - wrpr %g7, %pstate; \ - \ - /* Restore the o registers */ \ - ldx [%g1 + 0xd0], %o0; \ - ldx [%g1 + 0xd8], %o1; \ - ldx [%g1 + 0xe0], %o2; \ - ldx [%g1 + 0xe8], %o3; \ - ldx [%g1 + 0xf0], %o4; \ - ldx [%g1 + 0xf8], %o5; \ - ldx [%g1 + 0x100], %o6; \ - ldx [%g1 + 0x108], %o7; \ - \ - /* Restore the trap state */ \ - add %g1, 0x50, %g5; \ - mov 4, %g6; \ - \ -restore_trap_state_##type: \ - deccc %g6; \ - wrpr %g6, %tl; \ - ldx [%g5], %g7; \ - wrpr %g7, %tpc; \ - ldx [%g5 + 0x8], %g7; \ - wrpr %g7, %tnpc; \ - ldx [%g5 + 0x10], %g7; \ - wrpr %g7, %tstate; \ - ldx [%g5 + 0x18], %g7; \ - wrpr %g7, %tt; \ - bne restore_trap_state_##type; \ - add %g5, 0x20, %g5; \ - \ - ldx [%g1 + 0x38], %g7; \ - wr %g7, 0, %y; \ - ldx [%g1 + 0x40], %g7; \ - wr %g7, 0, %fprs; \ - ldx [%g1 + 0x48], %g7; \ - wrpr %g7, %tl; \ - \ - /* Restore exception stack pointer to previous value */ \ - setx tlb_handler_stack_pointer, %g7, %g6; \ - add %g1, 0x510, %g1; \ - stx %g1, [%g6]; - .globl reload_DMMU_tlb, reload_IMMU_tlb, bug reload_DMMU_tlb: - + + /* Save CPU state to stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, -CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] + SAVE_CPU_STATE(dtlb) - /* Switch to TLB locked stack space (note we add an additional 192 bytes required for + /* Switch to 8K TLB locked OpenBIOS stack (note we add an additional 192 bytes required for gcc to save its arguments when building with -O0) */ - add %g1, -STACK_BIAS - 192, %sp + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g6 + setx CONTEXT_STACK_SIZE, %g4, %g5 + sub %g6, %g5, %g6 + stx %g6, [%g7] + + setx - 2047 - 192, %g6, %g7 + add %g1, %g7, %g7 + mov %g7, %sp /* Enable interrupts for window spill/fill traps */ rdpr %pstate, %g7 @@ -577,18 +365,44 @@ reload_DMMU_tlb: rdpr %pstate, %g7 andn %g7, PSTATE_IE, %g7 wrpr %g7, %pstate - + + /* Restore CPU state from stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + setx CONTEXT_STACK_SIZE, %g4, %g5 + add %g1, %g5, %g1 + stx %g1, [%g7] + RESTORE_CPU_STATE(dtlb) - + + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] + retry reload_IMMU_tlb: - + + /* Save CPU state to stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, -CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] + SAVE_CPU_STATE(itlb) - /* Switch to TLB locked stack space (note we add an additional 192 bytes required for + /* Switch to 8K TLB locked OpenBIOS stack (note we add an additional 192 bytes required for gcc to save its arguments when building with -O0) */ - add %g1, -STACK_BIAS - 192, %sp + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g6 + setx CONTEXT_STACK_SIZE, %g4, %g5 + sub %g6, %g5, %g6 + stx %g6, [%g7] + + setx - 2047 - 192, %g6, %g7 + add %g1, %g7, %g7 + mov %g7, %sp /* Enable interrupts for window spill/fill traps */ rdpr %pstate, %g7 @@ -602,8 +416,20 @@ reload_IMMU_tlb: rdpr %pstate, %g7 andn %g7, PSTATE_IE, %g7 wrpr %g7, %pstate - + + /* Restore CPU state from stack */ + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + setx CONTEXT_STACK_SIZE, %g4, %g5 + add %g1, %g5, %g1 + stx %g1, [%g7] + RESTORE_CPU_STATE(itlb) + + setx _fcstack_ptr, %g6, %g7 + ldx [%g7], %g1 + add %g1, CONTEXT_STATE_SIZE, %g1 + stx %g1, [%g7] retry -- cgit 1.2.3-korg