qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] Enable support for PPC64 on qemu target


From: Laurent Vivier
Subject: Re: [Qemu-devel] [PATCH] Enable support for PPC64 on qemu target
Date: Thu, 26 Feb 2009 23:35:45 +0100

Hi,

see comments below.

Le 26 févr. 09 à 22:15, Alexander Graf a écrit :

This patch enables OpenBIOS to initialize on PPC64, enabling support for -cpu 970fx. It gets up to the boot prompt and works rather good so far, though I haven't been able to run a kernel yet.

For more recent PowerPC CPUs the PTE layout has changed, so we need to take that into account and create PTEs according to the new layout and at the new physical positions.

Signed-off-by: Alexander Graf <address@hidden>

Index: arch/ppc/qemu/init.c
===================================================================
--- arch/ppc/qemu/init.c        (revision 459)
+++ arch/ppc/qemu/init.c        (working copy)
@@ -230,6 +230,19 @@
 }

 static void
+cpu_g5_init(const struct cpudef *cpu)
+{
+    cpu_generic_init(cpu);
+
+    PUSH(0);
+    fword("encode-int");
+    push_str("reg");
+    fword("property");
+
+    fword("finish-device");
+}

As you use "970fx" in ppc_defs[], name should be "cpu_970_init()".

+static void
 cpu_g4_init(const struct cpudef *cpu)
 {
     cpu_generic_init(cpu);
@@ -359,6 +372,18 @@
         .clock_frequency = 0x1dcd6500,
         .initfn = cpu_g4_init,
     },
+    { // XXX find out real values
+        .iu_version = 0x003C0000,
+        .name = "PowerPC 970fx",

could you check on a real machine, according other values it seems it should be "PowerPC,970FX". (also, there are some examples in linux/Documentation/powerpc/booting- without-of.txt).
I'm not able to do a "dev /cpus/PowerPC 970fx"...

+        .icache_size = 0x8000,
+        .dcache_size = 0x8000,
+        .icache_sets = 0x80,
+        .dcache_sets = 0x80,
+        .icache_block_size = 0x20,
+        .dcache_block_size = 0x20,
+        .clock_frequency = 0x1dcd6500,
+        .initfn = cpu_g5_init,
+    },
 };

cpu_970_init() ?

 static const struct cpudef *
Index: arch/ppc/qemu/ofmem.c
===================================================================
--- arch/ppc/qemu/ofmem.c       (revision 459)
+++ arch/ppc/qemu/ofmem.c       (working copy)
@@ -23,6 +23,7 @@
 #include "mmutypes.h"
 #include "asm/processor.h"

+#define PPC64

Is it really needed ?

 #define BIT(n)         (1U<<(31-(n)))

 #define FREE_BASE              0x00004000
@@ -620,10 +621,80 @@
        return phys;
 }

+#ifdef PPC64
 static void
-hash_page( ulong ea, ulong phys, int mode )
+hash_page_64( ulong ea, ulong phys, int mode )
 {
        static int next_grab_slot=0;
+       uint64_t vsid_mask, page_mask, pgidx, hash;
+       uint64_t htab_mask, mask, avpn;
+       ulong pgaddr;
+       int i, found;
+       unsigned int vsid, vsid_sh, sdr, sdr_sh, sdr_mask;
+       mPTE_64_t *pp;
+
+#define TARGET_PAGE_BITS 12

in include/ofmem.h, we already have PAGE_SHIFT

+
+       vsid = (ea>>28) + SEGR_BASE;
+       vsid_sh = 7;
+       vsid_mask = 0x00003FFFFFFFFF80ULL;
+       asm ( "mfsdr1 %0" : "=r" (sdr) );
+       sdr_sh = 18;
+       sdr_mask = 0x3FF80;
+       page_mask = 0x0FFFFFFF; // XXX correct?
+       pgidx = (ea & page_mask) >> TARGET_PAGE_BITS;
+       avpn = (vsid << 12) | ((pgidx >> 4) & 0x0F80);;
+
+       hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
+       htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
+       mask = (htab_mask << sdr_sh) | sdr_mask;
+       pgaddr = sdr | (hash & mask);
+       pp = (mPTE_64_t *)pgaddr;
+
+       /* replace old translation */
+       for( found=0, i=0; !found && i<8; i++ )
+               if( pp[i].avpn == avpn )
+                       found=1;
+
+       /* otherwise use a free slot */
+       for( i=0; !found && i<8; i++ )
+               if( !pp[i].v )
+                       found=1;
+
+       /* out of slots, just evict one */
+       if( !found ) {
+               i = next_grab_slot + 1;
+               next_grab_slot = (next_grab_slot + 1) % 8;
+       }
+       i--;
+       {
+       mPTE_64_t p = {
+               // .avpn_low = avpn,
+               .avpn = avpn >> 7,
+               .h = 0,
+               .v = 1,
+
+               .rpn = (phys & ~0xfff) >> 12,
+               .r = mode & (1 << 8) ? 1 : 0,
+               .c = mode & (1 << 7) ? 1 : 0,
+               .w = mode & (1 << 6) ? 1 : 0,
+               .i = mode & (1 << 5) ? 1 : 0,
+               .m = mode & (1 << 4) ? 1 : 0,
+               .g = mode & (1 << 3) ? 1 : 0,
+               .n = mode & (1 << 2) ? 1 : 0,
+               .pp = mode & 3,
+       };
+       pp[i] = p;
+       }
+
+       asm volatile( "tlbie %0"  :: "r"(ea) );
+}
+#endif
+
+static void
+hash_page_32( ulong ea, ulong phys, int mode )
+{
+       static int next_grab_slot=0;
        ulong *upte, cmp, hash1;
        int i, vsid, found;
        mPTE_t *pp;
@@ -660,6 +731,26 @@
        asm volatile( "tlbie %0"  :: "r"(ea) );
 }

+#ifdef PPC64
+static int is_ppc64(void)
+{
+       unsigned int pvr;
+       asm volatile("mfspr %0, 0x11f" : "=r" (pvr) );
+
+       return ((pvr >= 0x330000) && (pvr < 0x70330000));
+}
+#endif
+
+static void hash_page( ulong ea, ulong phys, int mode )
+{
+#ifdef PPC64
+       if ( is_ppc64() )
+               hash_page_64(ea, phys, mode);
+       else
+#endif
+               hash_page_32(ea, phys, mode);
+}
+
 void
 dsi_exception( void )
 {
@@ -706,7 +797,14 @@

        /* SDR1: Storage Description Register 1 */

-       hash_base = (ramsize - 0x00100000 - HASH_SIZE) & 0xffff0000;
+#ifdef PPC64
+       if(is_ppc64()) {
+           hash_base = (ramsize - 0x00200000 - HASH_SIZE) & 0xfff00000;

Why is it 0x00200000 ?

Please update comment (and code...) in arch/ppc/qemu/start.S !

+       } else
+#endif
+       {
+           hash_base = (ramsize - 0x00100000 - HASH_SIZE) & 0xffff0000;
+       }
         memset((void *)hash_base, 0, HASH_SIZE);
        sdr1 = hash_base | ((HASH_SIZE-1) >> 16);
        asm volatile("mtsdr1 %0" :: "r" (sdr1) );
Index: arch/ppc/qemu/mmutypes.h
===================================================================
--- arch/ppc/qemu/mmutypes.h    (revision 459)
+++ arch/ppc/qemu/mmutypes.h    (working copy)
@@ -38,7 +38,29 @@
        unsigned long pp:2;     /* Page protection */
 } mPTE_t;

+#define uint64_t unsigned long long

uint64_t is defined in include/ppc/types.h

+typedef struct mPTE_64 {
+       uint32_t avpn_low;      /* Abbreviated Virtual Page Number (unused) */
+       uint32_t avpn:25;       /* Abbreviated Virtual Page Number */
+       uint32_t sw:4;          /* Software Use */
+       uint32_t  :1;           /* Reserved */
+       uint32_t h:1;           /* Hash algorithm indicator */
+       uint32_t v:1;           /* Entry is valid */

+       uint32_t rpn_low;       /* Real (physical) page number (unused) */
+       uint32_t rpn:20;        /* Real (physical) page number */
+       uint32_t    :2;         /* Reserved */
+       uint32_t ac:1;          /* Address Compare*/
+       uint32_t r:1;           /* Referenced */
+       uint32_t c:1;           /* Changed */
+       uint32_t w:1;           /* Write-thru cache mode */
+       uint32_t i:1;           /* Cache inhibited */
+       uint32_t m:1;           /* Memory coherence */
+       uint32_t g:1;           /* Guarded */
+       uint32_t n:1;           /* No-Execute */
+       uint32_t pp:2;          /* Page protection */
+} mPTE_64_t;


Could you use "unsigned long" like in other definitions to be consistent ?

 typedef struct _mBATU {                /* Upper part of BAT (all except 601) */
unsigned long bepi:15; /* Effective page index (virtual address) */
         unsigned long :4;      /* Unused */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]