[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XenPPC] [pushed] [ppc] U4 DART enablement for JS21
changeset: 9958:786d4a84bdad6467f780967e7725581f44678d9a user: jimix@xxxxxxxxxxxxxxxxxxxxx date: Fri Apr 28 17:44:52 2006 -0400 files: xen/arch/ppc/Makefile xen/arch/ppc/boot_of.c xen/arch/ppc/dart.c xen/arch/ppc/dart.h xen/arch/ppc/dart_u4.c xen/arch/ppc/iommu_u3.c description: [ppc] U4 DART enablement for JS21 - discover the DART and model from the devtree - place common code in single file - isolate U3 DART code - write U4 DART code - rewrite invalidate retry code so it actually makes sense diff -r ffa41af2e455738f8fe3a0af8ae8952e9d4cc47c -r 786d4a84bdad6467f780967e7725581f44678d9a xen/arch/ppc/Makefile --- a/xen/arch/ppc/Makefile Thu Apr 27 14:40:10 2006 -0400 +++ b/xen/arch/ppc/Makefile Fri Apr 28 17:44:52 2006 -0400 @@ -8,6 +8,8 @@ obj-y += audit.o obj-y += audit.o obj-y += bitops.o obj-y += boot_of.o +obj-y += dart.o +obj-y += dart_u4.o obj-y += delay.o obj-y += dom0_ops.o obj-y += domain_build.o diff -r ffa41af2e455738f8fe3a0af8ae8952e9d4cc47c -r 786d4a84bdad6467f780967e7725581f44678d9a xen/arch/ppc/boot_of.c --- a/xen/arch/ppc/boot_of.c Thu Apr 27 14:40:10 2006 -0400 +++ b/xen/arch/ppc/boot_of.c Fri Apr 28 17:44:52 2006 -0400 @@ -24,6 +24,7 @@ #include <xen/compile.h> #include <public/of-devtree.h> #include <asm/page.h> +#include "dart.h" static ulong of_vec; static ulong of_msr; @@ -824,15 +825,12 @@ static void boot_of_module(ulong r3, ulo mbi->flags |= MBI_MODULES; mbi->mods_count = 2; mbi->mods_addr = (u32)mods; - } static int __init boot_of_serial(void) { - /* right now we are punting and using mambo writes which is the - * hardcoded setup */ - + /* fill this in */ return 1; } @@ -889,6 +887,35 @@ static void __init boot_of_pic(void) opic_addr |= addr[1]; } of_printf("OF: found OpenPIC at: 0x%lx\n", opic_addr); +} + +static void __init boot_of_dart(void) +{ + int n; + + n = of_finddevice("/mambo"); + if (n != OF_FAILURE) { + /* mambo had no dart */ + return; + } + + /* defaults */ + dart_address = DART_DEF_BASE; + dart_model = DART_U3; + + /* this is not great but is sufficient */ + n = of_finddevice("/dart"); + if (n != OF_FAILURE) { + char compat[128]; + + of_getprop(n, "reg", &dart_address, sizeof (dart_address)); + + compat[0] = '\0'; + of_getprop(n, "compatible", compat, sizeof (compat)); + if (strstr(compat, "u4")) { + dart_model = DART_U4; + } + } } multiboot_info_t __init *boot_of_init( @@ -928,6 +955,7 @@ multiboot_info_t __init *boot_of_init( boot_of_cpus(); boot_of_rtas(); boot_of_pic(); + boot_of_dart(); /* end of OF */ of_printf("closing OF stdout...\n"); diff -r ffa41af2e455738f8fe3a0af8ae8952e9d4cc47c -r 786d4a84bdad6467f780967e7725581f44678d9a xen/arch/ppc/iommu_u3.c --- a/xen/arch/ppc/iommu_u3.c Thu Apr 27 14:40:10 2006 -0400 +++ b/xen/arch/ppc/iommu_u3.c Fri Apr 28 17:44:52 2006 -0400 @@ -21,18 +21,13 @@ #include <xen/config.h> #include <xen/types.h> #include <xen/sched.h> -#include <xen/init.h> #include <xen/mm.h> #include <public/xen.h> #include <asm/io.h> #include <asm/current.h> #include "tce.h" #include "iommu.h" - -#define DART_VALID 0x80000000 -#define DART_MASK 0x00ffffff -#define DART_BASE 0xf8033000UL -#define DART_SHIFT 21 +#include "dart.h" union dart_ctl { u32 dc_word; @@ -45,162 +40,67 @@ union dart_ctl { } reg; }; -#ifdef DEBUG -static int first_put = 0; -#endif +static u32 volatile *dart_ctl_reg; -static u32 *dart_table; -static ulong dummy_page; -static u32 *dart_ctl_reg; +static void u3_inv_all(void) +{ + union dart_ctl dc; + ulong r = 0; + int l = 0; -static void fill_dart(ulong index, ulong rpg, ulong num_pg) -{ - u32 volatile *entry = dart_table + index; - ulong i = 0; - ulong last_flush = 0; + for (;;) { + dc.dc_word = in_32(dart_ctl_reg); + dc.reg.dc_invtlb = 1; + out_32(dart_ctl_reg, dc.dc_word); - while (1) { - entry[i] = DART_VALID | (rpg & DART_MASK); - ++i; - ++rpg; - if (i == num_pg) break; + do { + dc.dc_word = in_32(dart_ctl_reg); + r++; + } while ((dc.reg.dc_invtlb == 1) && (r < (1 << l))); - if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) { - last_flush = (ulong)&entry[i - 1]; - dcbst(last_flush); + if (r == (1 << l)) { + if (l < 4) { + l++; + dc.dc_word = in_32(dart_ctl_reg); + dc.reg.dc_invtlb = 0; + out_32(dart_ctl_reg, dc.dc_word); + continue; + } else { + panic(" broken U3???\n"); + } } + return; } - dcbst((ulong) &entry[i - 1]); } -static void clear_dart(ulong index, ulong num_pg) +static void u3_inv_entry(ulong pg) { - u32 *entry = dart_table + index; - ulong i = 0; - ulong rpg = dummy_page; - ulong last_flush = 0; - - while (1) { - entry[i] = DART_VALID | (rpg & DART_MASK); - ++i; - if (i == num_pg) break; - - if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) { - last_flush = (ulong)&entry[i - 1]; - dcbst(last_flush); - } - } - dcbst((ulong)&entry[i - 1]); + /* sadly single entry invalidation has been reported not to work */ + u3_inv_all(); } -static void invtlb_dart(void) +static struct dart_ops u3_ops = { + .do_inv_all = u3_inv_all, + .do_inv_entry = u3_inv_entry, +}; + +struct dart_ops *u3_init(ulong base, ulong table, ulong tpgs) { union dart_ctl dc; - ulong retries = 0; - dc.dc_word = in_32(dart_ctl_reg); - dc.reg.dc_invtlb = 1; + dart_ctl_reg = (u32 *)base; + + dc.dc_word = 0; + + dc.reg.dc_base = table >> PAGE_SHIFT; + dc.reg.dc_size = 1 << tpgs; + dc.reg.dc_enable = 1; + + + printk("Initializing DART Model U3: reg: %p word: %x\n", + dart_ctl_reg, dc.dc_word); out_32(dart_ctl_reg, dc.dc_word); - do { - union dart_ctl copy; - - copy.dc_word = in_32(dart_ctl_reg); - if (copy.reg.dc_invtlb == 0) { - break; - } - - ++retries; - if ((retries & 3) == 0) { - copy.reg.dc_invtlb = 0; - out_32(dart_ctl_reg, copy.dc_word); - copy.dc_word = in_32(dart_ctl_reg); - out_32(dart_ctl_reg, dc.dc_word); - } - } while (1); + return &u3_ops; } - -static int u3_put(ulong ioba, union tce tce) -{ - ulong index = ioba >> PAGE_SHIFT; - - if (index > (1 << DART_SHIFT) / sizeof(u32)) { - return -1; - } - - if (tce.tce_bits.tce_vlps != 0 || tce.tce_bits.tce_lpx != 0) { - panic("no support for large TCEs\n"); - } - - if (tce.tce_bits.tce_read || tce.tce_bits.tce_write) { -#ifdef DEBUG - printk("<DART[0x%lx]: ioba: 0x%lx rpn:0x%lx\n", - index, ioba, tce.tce_bits.tce_rpn); - first_put = 1; -#endif - fill_dart(index, tce.tce_bits.tce_rpn, 1); - } else { -#ifdef DEBUG - if (first_put) { - printk(">DART[0x%lx]\n", index); - } -#endif - clear_dart(index, 1); - } - invtlb_dart(); - - return 0; -} - -static int init_u3(void) -{ - union dart_ctl dc; - - if (on_mambo()) { - return 0; - } - - /* SLOF doesn't provide DART address */ - dart_ctl_reg = (u32 *)DART_BASE; - - /* Max size of 512 pages == 2MB == 1<<21 */ - dart_table = alloc_xenheap_pages(DART_SHIFT - PAGE_SHIFT); - - /* Linux uses a dummy page, filling "empty" DART entries with a - reference to this page to capture stray DMA's */ - dummy_page = (ulong)alloc_xenheap_pages(1) >> PAGE_SHIFT; - memset((void *)(dummy_page << PAGE_SHIFT), 0, 1 << PAGE_SHIFT); - -#ifdef DARB_EXAMPLE - if (0) { - ulong dabr = 0x44590b3; //0xf7fe70b3; //0xc003; // DABR 1013 DABRX 1015 - ulong dabrx = 0xd; - asm volatile("mtspr 1013,%0; mtspr 1015,%1" - : : "r" (dabr), "r" (dabrx) : "memory"); - } -#endif - - clear_dart(0, (1 << DART_SHIFT) / sizeof(u32)); - - dc.dc_word = 0; - - dc.reg.dc_base = ((ulong)dart_table) >> PAGE_SHIFT; - dc.reg.dc_size = 1 << (DART_SHIFT - PAGE_SHIFT); - dc.reg.dc_enable = 1; - - - printk("Initializing U3 DART: tbl: %p[0x%lx] ctl reg: %p word: %x " - "dummy: 0x%lx\n", - dart_table, (1 << DART_SHIFT) / sizeof(u32), - dart_ctl_reg, dc.dc_word, dummy_page); - - out_32(dart_ctl_reg, dc.dc_word); - - invtlb_dart(); - - iommu_register(0, u3_put); - - return 0; -} -__initcall(init_u3); diff -r ffa41af2e455738f8fe3a0af8ae8952e9d4cc47c -r 786d4a84bdad6467f780967e7725581f44678d9a xen/arch/ppc/dart.c --- /dev/null Thu Jan 1 00:00:00 1970 +0000 +++ b/xen/arch/ppc/dart.c Fri Apr 28 17:44:52 2006 -0400 @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <xen/config.h> +#include <xen/types.h> +#include <xen/mm.h> +#include <asm/cache.h> +#include <xen/init.h> +#include "tce.h" +#include "iommu.h" +#include "dart.h" + +#undef DEBUG +#ifdef DEBUG +static int first_put; +#endif + +#define DART_SHIFT 21 + +int dart_model; +unsigned long dart_address; + +static ulong dummy_page; +static struct dart_ops *dops; +static u32 *dart_table; + +union dart_tce { + u32 dt_word; + struct { + u32 dt_v:1; /* valid */ + u32 dt_r:1; /* read */ + u32 dt_w:1; /* write */ + u32 _dt_res:5; + u32 dt_ppn:24; /* 24 bit Physical Page Number + * representing address [28:51] */ + } dt_bits; +}; + +static u32 dart_encode(int perm, ulong rpn) +{ + union dart_tce tce; + + tce.dt_word = 0; + tce.dt_bits.dt_v = 1; + tce.dt_bits.dt_ppn = rpn; + + if (perm & DART_READ) { + tce.dt_bits.dt_r = 1; + } + if (perm & DART_WRITE) { + tce.dt_bits.dt_w = 1; + } + + return tce.dt_word; +} + +static void dart_fill(ulong index, int perm, ulong rpg, ulong num_pg) +{ + u32 volatile *entry = dart_table + index; + ulong i = 0; + ulong last_flush = 0; + + while (1) { + entry[i] = dart_encode(perm, rpg); + ++i; + ++rpg; + if (i == num_pg) break; + + if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) { + last_flush = (ulong)&entry[i - 1]; + dcbst(last_flush); + } + } + dcbst((ulong) &entry[i - 1]); +} + +static void dart_clear(ulong index, ulong num_pg) +{ + u32 *entry = dart_table + index; + ulong i = 0; + ulong rpg = dummy_page; + ulong last_flush = 0; + + while (1) { + entry[i] = dart_encode(DART_READ | DART_WRITE, rpg); + ++i; + if (i == num_pg) break; + + if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) { + last_flush = (ulong)&entry[i - 1]; + dcbst(last_flush); + } + } + dcbst((ulong)&entry[i - 1]); +} + +static int dart_put(ulong ioba, union tce tce) +{ + ulong index = ioba >> PAGE_SHIFT; + int perm = 0; + + if (index > (1 << DART_SHIFT) / sizeof(u32)) { + return -1; + } + + if (tce.tce_bits.tce_vlps != 0 || tce.tce_bits.tce_lpx != 0) { + panic("no support for large TCEs\n"); + } + + if (tce.tce_bits.tce_read) { + perm |= DART_READ; + } + if (tce.tce_bits.tce_write) { + perm |= DART_WRITE; + } + if (perm != 0) { +#ifdef DEBUG + printk("<DART[0x%lx]: ioba: 0x%lx rpn:0x%lx\n", + index, ioba, tce.tce_bits.tce_rpn); + first_put = 1; +#endif + dart_fill(index, perm, tce.tce_bits.tce_rpn, 1); + } else { +#ifdef DEBUG + if (first_put) { + printk(">DART[0x%lx]\n", index); + } +#endif + dart_clear(index, 1); + } + dops->do_inv_entry(tce.tce_bits.tce_rpn); + + return 0; +} + +static int init_dart(void) +{ + ulong tpgs; + + switch (dart_model) { + case DART_U3: case DART_U4: + break; + default: + panic("unknown DART model: %d\n", dart_model); + /* FALLTHRU */ + case 0: + return 0; + } + + /* Max size of 512 pages == 2MB == 1<<21 */ + tpgs = DART_SHIFT - PAGE_SHIFT; + dart_table = alloc_xenheap_pages(tpgs); + + /* Linux uses a dummy page, filling "empty" DART entries with a + reference to this page to capture stray DMA's */ + dummy_page = (ulong)alloc_xenheap_pages(1) >> PAGE_SHIFT; + memset((void *)(dummy_page << PAGE_SHIFT), 0, 1 << PAGE_SHIFT); + + printk("Initializing DART 0x%lx: tbl: 0x%lx[0x%lx] dummy: 0x%lx\n", + dart_address, (ulong)dart_table, (1 << DART_SHIFT) / sizeof(u32), + dummy_page); + + /* register this iommu */ + iommu_register(0, dart_put); + + switch (dart_model) { + case DART_U3: + dops = u3_init(dart_address, (ulong)dart_table, tpgs); + break; + case DART_U4: + dops = u4_init(dart_address, (ulong)dart_table, tpgs); + break; + } + + dart_clear(0, (1 << DART_SHIFT) / sizeof(u32)); + dops->do_inv_all(); +printk("%s: done!\n", __func__); + return 0; +} +__initcall(init_dart); diff -r ffa41af2e455738f8fe3a0af8ae8952e9d4cc47c -r 786d4a84bdad6467f780967e7725581f44678d9a xen/arch/ppc/dart.h --- /dev/null Thu Jan 1 00:00:00 1970 +0000 +++ b/xen/arch/ppc/dart.h Fri Apr 28 17:44:52 2006 -0400 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _DART_H +#define _DART_H + +#include <xen/config.h> +#include <xen/types.h> + +#define DART_DEF_BASE 0xf8033000UL +#define DART_NONE 0 +#define DART_U3 3 +#define DART_U4 4 +#define DART_WRITE 0x1 +#define DART_READ 0x2 + +extern int dart_model; +extern unsigned long dart_address; + +struct dart_ops { + void (*do_inv_all)(void); + void (*do_inv_entry)(ulong pg); +}; + +extern struct dart_ops *u3_init(ulong base, ulong table, ulong tpgs); +extern struct dart_ops *u4_init(ulong base, ulong table, ulong tpgs); + +#endif /* _DART_H */ + diff -r ffa41af2e455738f8fe3a0af8ae8952e9d4cc47c -r 786d4a84bdad6467f780967e7725581f44678d9a xen/arch/ppc/dart_u4.c --- /dev/null Thu Jan 1 00:00:00 1970 +0000 +++ b/xen/arch/ppc/dart_u4.c Fri Apr 28 17:44:52 2006 -0400 @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#undef DEBUG + +#include <xen/config.h> +#include <xen/types.h> +#include <xen/sched.h> +#include <xen/init.h> +#include <xen/mm.h> +#include <public/xen.h> +#include <asm/io.h> +#include <asm/current.h> +#include "tce.h" +#include "iommu.h" +#include "dart.h" + +#define TOO_MANY_RETRIES ~0 + +union dart_ctl { + u32 dc_word; + struct { + u32 dc_darten:1; /* DART Enable (0:disabled) */ + u32 dc_ione:1; /* Invalidate one DART TLB entry (using ILPN) */ + u32 dc_iall:1; /* Invalidate all DART TLB entries */ + u32 dc_idle:1; /* DART is idle */ + u32 dc_peen:1; /* Parity Checking is enabled */ + u32 dc_ilpn:27; /* 27-bit Logical Page Address for + * invalidating one TLB entry */ + } dc_bits; +}; + +union dart_base { + u32 db_word; + struct { + u32 _db_resv:8; + u32 db_dartbase:24; /* Base Address of DART (4K byte Alignment) */ + } db_bits; +}; + +union dart_size { + u32 ds_word; + struct { + u32 _ds_resv:15; + u32 ds_dartsize:17; /* Size of Dart in 4K-Byte Pages */ + } ds_bits; +}; + +union dart_excp { + u32 de_word; + struct { + u32 de_rqsrc:1; /* Request Source. [0:PCIE, 1:HT] */ + u32 de_lpn:27; /* 27Ðbit Logical Address of Exception [25:51] */ + u32 de_rqop:1; /* Request operation. [0:Read, 1:Write] */ + u32 de_xcd:3; /* Exception code */ + } de_bits; +}; + +struct dart { + /* 0x00 */ + union dart_ctl d_dartcntl; + u32 _pad0x04_0x10[3]; + /* 0x10 */ + union dart_base d_dartbase; + u32 _pad0x14_0x20[3]; + /* 0x20 */ + union dart_size d_dartsize; + u32 _pad0x24_0x30[3]; + /* 0x30 */ + union dart_excp d_dartexcp; + u32 _pad0x34_0x40[3]; +}; + +static volatile struct dart *dart; + +static void u4_inv_all(void) +{ + union dart_ctl dc; + ulong r = 0; + int l = 0; + + for (;;) { + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); + dc.dc_bits.dc_iall = 1; + out_32(&dart->d_dartcntl.dc_word, dc.dc_word); + + do { + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); + r++; + } while ((dc.dc_bits.dc_iall == 1) && (r < (1 << l))); + + if (r == (1 << l)) { + if (l < 4) { + l++; + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); + dc.dc_bits.dc_iall = 0; + out_32(&dart->d_dartcntl.dc_word, dc.dc_word); + continue; + } else { + panic(" broken U4???\n"); + } + } + return; + } +} + +static void u4_inv_entry(ulong pgn) +{ + union dart_ctl dc; + ulong retries = 0; + + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); + dc.dc_bits.dc_ilpn = pgn; + dc.dc_bits.dc_ione = 1; + out_32(&dart->d_dartcntl.dc_word, dc.dc_word); + + /* wait for completion */ + /* FIXME: since we do this from the HV do we need to wait?! */ + do { + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); + retries++; + if (retries > 1000000) + panic("WAY! too long\n"); + } while (dc.dc_bits.dc_ione != 0); +} + +static struct dart_ops u4_ops = { + .do_inv_all = u4_inv_all, + .do_inv_entry = u4_inv_entry, +}; + +struct dart_ops *u4_init(ulong base, ulong table, ulong tpgs) +{ + union dart_base db; + union dart_size ds; + union dart_ctl dc; + + dart = (struct dart *)base; + + db.db_word = 0; + db.db_bits.db_dartbase = table >> PAGE_SHIFT; + + ds.ds_word = 0; + ds.ds_bits.ds_dartsize = tpgs; + + dc.dc_word = 0; + dc.dc_bits.dc_darten = 1; + + /* make sure its disabled */ + out_32(&dart->d_dartcntl.dc_word, 0); + + printk("Initializing DART Model U4: ctl: 0x%x base: 0x%x size: 0x%x\n", + dc.dc_word, db.db_word, ds.ds_word); + + out_32(&dart->d_dartbase.db_word, db.db_word); + out_32(&dart->d_dartsize.ds_word, ds.ds_word); + out_32(&dart->d_dartcntl.dc_word, dc.dc_word); + + return &u4_ops; +} _______________________________________________ Xen-ppc-devel mailing list Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-ppc-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |