svn commit: r212101 - in user/nwhitehorn/ps3/powerpc: aim include
powerpc ps3
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Wed Sep 1 17:02:31 UTC 2010
Author: nwhitehorn
Date: Wed Sep 1 17:02:31 2010
New Revision: 212101
URL: http://svn.freebsd.org/changeset/base/212101
Log:
Enable use of the high 128 MB of memory on the PS3. On PowerPC hypervisors,
only a limited subset of physical memory is typically available in real
mode. In addition, the information on what that subset is is typically
hypervisor privileged. This commit extends the platform interface to
provide a hook for querying that information, and modifies the small
amounts of the kernel that care to use it appropriately.
Modified:
user/nwhitehorn/ps3/powerpc/aim/mmu_oea64.c
user/nwhitehorn/ps3/powerpc/aim/slb.c
user/nwhitehorn/ps3/powerpc/aim/uma_machdep.c
user/nwhitehorn/ps3/powerpc/include/platform.h
user/nwhitehorn/ps3/powerpc/include/vmparam.h
user/nwhitehorn/ps3/powerpc/powerpc/platform.c
user/nwhitehorn/ps3/powerpc/powerpc/platform_if.m
user/nwhitehorn/ps3/powerpc/ps3/if_glc.c
user/nwhitehorn/ps3/powerpc/ps3/if_glcreg.h
user/nwhitehorn/ps3/powerpc/ps3/mmu_ps3.c
user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c
Modified: user/nwhitehorn/ps3/powerpc/aim/mmu_oea64.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/aim/mmu_oea64.c Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/aim/mmu_oea64.c Wed Sep 1 17:02:31 2010 (r212101)
@@ -2338,6 +2338,9 @@ moea64_bootstrap_alloc(vm_size_t size, u
if (s < phys_avail[i] || e > phys_avail[i + 1])
continue;
+ if (s + size > platform_real_maxaddr())
+ continue;
+
if (s == phys_avail[i]) {
phys_avail[i] += size;
} else if (e == phys_avail[i + 1]) {
Modified: user/nwhitehorn/ps3/powerpc/aim/slb.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/aim/slb.c Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/aim/slb.c Wed Sep 1 17:02:31 2010 (r212101)
@@ -40,11 +40,14 @@
#include <vm/vm_map.h>
#include <machine/md_var.h>
+#include <machine/platform.h>
#include <machine/pmap.h>
#include <machine/vmparam.h>
uintptr_t moea64_get_unique_vsid(void);
void moea64_release_vsid(uint64_t vsid);
+void *uma_small_alloc_core(uma_zone_t zone, int bytes, u_int8_t *flags,
+ int wait, vm_offset_t minphys, vm_offset_t maxphys);
struct slbcontainer {
struct slb slb;
@@ -273,6 +276,18 @@ slb_compare(struct slbcontainer *a, stru
return (1);
}
+static void *
+slb_uma_cache_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
+{
+ static vm_offset_t realmax = 0;
+
+ if (realmax == 0)
+ realmax = platform_real_maxaddr();
+
+ return (uma_small_alloc_core(zone, bytes, flags, wait, 0, realmax));
+}
+
+
static void
slb_zone_init(void *dummy)
{
@@ -281,6 +296,9 @@ slb_zone_init(void *dummy)
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
slb_cache_zone = uma_zcreate("SLB cache", 64*sizeof(struct slb),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
+
+ if (platform_real_maxaddr() != VM_MAX_ADDRESS)
+ uma_zone_set_allocf(slb_cache_zone, slb_uma_cache_alloc);
}
struct slb *
Modified: user/nwhitehorn/ps3/powerpc/aim/uma_machdep.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/aim/uma_machdep.c Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/aim/uma_machdep.c Wed Sep 1 17:02:31 2010 (r212101)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_kern.h>
#include <vm/vm_pageout.h>
#include <vm/vm_extern.h>
+#include <vm/vm_phys.h>
#include <vm/uma.h>
#include <vm/uma.h>
#include <vm/uma_int.h>
@@ -48,9 +49,20 @@ static int hw_uma_mdpages;
SYSCTL_INT(_hw, OID_AUTO, uma_mdpages, CTLFLAG_RD, &hw_uma_mdpages, 0,
"UMA MD pages in use");
+void *uma_small_alloc_core(uma_zone_t zone, int bytes, u_int8_t *flags,
+ int wait, vm_offset_t minphys, vm_offset_t maxphys);
+
void *
uma_small_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
{
+ return (uma_small_alloc_core(zone, bytes, flags, wait,
+ 0, VM_MAX_ADDRESS));
+}
+
+void *
+uma_small_alloc_core(uma_zone_t zone, int bytes, u_int8_t *flags, int wait,
+ vm_offset_t minphys, vm_offset_t maxphys)
+{
static vm_pindex_t color;
void *va;
vm_page_t m;
@@ -65,7 +77,12 @@ uma_small_alloc(uma_zone_t zone, int byt
pflags |= VM_ALLOC_ZERO;
for (;;) {
- m = vm_page_alloc(NULL, color++, pflags | VM_ALLOC_NOOBJ);
+ if (minphys == 0 && maxphys == VM_MAX_ADDRESS)
+ m = vm_page_alloc(NULL, color++,
+ pflags | VM_ALLOC_NOOBJ);
+ else
+ m = vm_phys_alloc_contig(1, minphys, maxphys, PAGE_SIZE,
+ PAGE_SIZE);
if (m == NULL) {
if (wait & M_NOWAIT)
return (NULL);
Modified: user/nwhitehorn/ps3/powerpc/include/platform.h
==============================================================================
--- user/nwhitehorn/ps3/powerpc/include/platform.h Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/include/platform.h Wed Sep 1 17:02:31 2010 (r212101)
@@ -44,6 +44,7 @@ struct mem_region {
};
void mem_regions(struct mem_region **, int *, struct mem_region **, int *);
+vm_offset_t platform_real_maxaddr(void);
u_long platform_timebase_freq(struct cpuref *);
Modified: user/nwhitehorn/ps3/powerpc/include/vmparam.h
==============================================================================
--- user/nwhitehorn/ps3/powerpc/include/vmparam.h Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/include/vmparam.h Wed Sep 1 17:02:31 2010 (r212101)
@@ -142,7 +142,11 @@ struct pmap_physseg {
/*
* The physical address space is densely populated.
*/
+#ifdef __powerpc64__
+#define VM_PHYSSEG_SPARSE
+#else
#define VM_PHYSSEG_DENSE
+#endif
/*
* Create three free page pools: VM_FREEPOOL_DEFAULT is the default pool
Modified: user/nwhitehorn/ps3/powerpc/powerpc/platform.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/powerpc/platform.c Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/powerpc/platform.c Wed Sep 1 17:02:31 2010 (r212101)
@@ -69,6 +69,12 @@ mem_regions(struct mem_region **phys, in
PLATFORM_MEM_REGIONS(plat_obj, phys, physsz, avail, availsz);
}
+vm_offset_t
+platform_real_maxaddr(void)
+{
+ return (PLATFORM_REAL_MAXADDR(plat_obj));
+}
+
const char *
installed_platform()
{
Modified: user/nwhitehorn/ps3/powerpc/powerpc/platform_if.m
==============================================================================
--- user/nwhitehorn/ps3/powerpc/powerpc/platform_if.m Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/powerpc/platform_if.m Wed Sep 1 17:02:31 2010 (r212101)
@@ -34,6 +34,7 @@
#include <machine/platform.h>
#include <machine/platformvar.h>
#include <machine/smp.h>
+#include <machine/vmparam.h>
/**
* @defgroup PLATFORM platform - KObj methods for PowerPC platform
@@ -66,6 +67,10 @@ CODE {
{
return (ENOENT);
}
+ static vm_offset_t platform_null_real_maxaddr(platform_t plat)
+ {
+ return (VM_MAX_ADDRESS);
+ }
};
/**
@@ -109,6 +114,15 @@ METHOD void mem_regions {
};
/**
+ * @brief Return the maximum address accessible in real mode
+ * (for use with hypervisors)
+ */
+METHOD vm_offset_t real_maxaddr {
+ platform_t _plat;
+} DEFAULT platform_null_real_maxaddr;
+
+
+/**
* @brief Get the CPU's timebase frequency, in ticks per second.
*
* @param _cpu CPU whose timebase to query
Modified: user/nwhitehorn/ps3/powerpc/ps3/if_glc.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/if_glc.c Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/ps3/if_glc.c Wed Sep 1 17:02:31 2010 (r212101)
@@ -49,6 +49,7 @@
#include <machine/pio.h>
#include <machine/bus.h>
+#include <machine/platform.h>
#include <machine/pmap.h>
#include <machine/resource.h>
#include <sys/bus.h>
@@ -110,13 +111,36 @@ glc_getphys(void *xaddr, bus_dma_segment
*(bus_addr_t *)xaddr = segs[0].ds_addr;
}
+static bus_addr_t
+glc_map_addr(struct glc_softc *sc, bus_addr_t lpar_addr)
+{
+ static struct mem_region *regions = NULL;
+ static int rcount;
+ int i;
+
+ if (regions == NULL)
+ mem_regions(®ions, &rcount, ®ions, &rcount);
+
+ for (i = 0; i < rcount; i++) {
+ if (lpar_addr >= regions[i].mr_start &&
+ lpar_addr < regions[i].mr_start + regions[i].mr_size)
+ break;
+ }
+
+ if (i == rcount)
+ panic("glc: unable to map address %#lx", lpar_addr);
+
+ return (sc->sc_dma_base[i] + (lpar_addr - regions[i].mr_start));
+}
+
static int
glc_attach(device_t dev)
{
struct glc_softc *sc;
struct glc_txsoft *txs;
+ struct mem_region *regions;
uint64_t mac64, val, junk;
- int i, err;
+ int i, err, rcount;
sc = device_get_softc(dev);
@@ -184,24 +208,29 @@ glc_attach(device_t dev)
*/
/* XXX: following should be integrated to busdma */
- err = lv1_allocate_device_dma_region(sc->sc_bus, sc->sc_dev,
- 0x8000000 /* 128 MB */, 24 /* log_2(16 MB) */,
- 0 /* 32-bit transfers */, &sc->sc_dma_base);
- if (err != 0) {
- device_printf(dev, "could not allocate DMA region: %d\n", err);
- goto fail;
- }
+ mem_regions(®ions, &rcount, ®ions, &rcount);
+ for (i = 0; i < rcount; i++) {
+ err = lv1_allocate_device_dma_region(sc->sc_bus, sc->sc_dev,
+ regions[i].mr_size, 24 /* log_2(16 MB) */,
+ 0 /* 32-bit transfers */, &sc->sc_dma_base[i]);
+ if (err != 0) {
+ device_printf(dev,
+ "could not allocate DMA region %d: %d\n", i, err);
+ goto fail;
+ }
- err = lv1_map_device_dma_region(sc->sc_bus, sc->sc_dev, 0 /* physmem */,
- sc->sc_dma_base, 0x8000000 /* 128 MB */,
- 0xf800000000000000UL /* see Cell IO/MMU docs */);
- if (err != 0) {
- device_printf(dev, "could not map DMA region: %d\n", err);
- goto fail;
+ err = lv1_map_device_dma_region(sc->sc_bus, sc->sc_dev,
+ regions[i].mr_start, sc->sc_dma_base[i], regions[i].mr_size,
+ 0xf800000000000000UL /* see Cell IO/MMU docs */);
+ if (err != 0) {
+ device_printf(dev,
+ "could not map DMA region %d: %d\n", i, err);
+ goto fail;
+ }
}
err = bus_dma_tag_create(bus_get_dma_tag(dev), 32, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
129*sizeof(struct glc_dmadesc), 1, 128*sizeof(struct glc_dmadesc),
0, NULL,NULL, &sc->sc_dmadesc_tag);
@@ -219,11 +248,11 @@ glc_attach(device_t dev)
&sc->sc_rxdmadesc_phys, 0);
err = bus_dma_tag_create(bus_get_dma_tag(dev), 128, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL,NULL,
&sc->sc_rxdma_tag);
err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE_32BIT, 16, BUS_SPACE_MAXSIZE_32BIT, 0, NULL,NULL,
&sc->sc_txdma_tag);
@@ -469,15 +498,15 @@ glc_add_rxbuf_dma(struct glc_softc *sc,
struct glc_rxsoft *rxs = &sc->sc_rxsoft[idx];
bzero(&sc->sc_rxdmadesc[idx], sizeof(sc->sc_rxdmadesc[idx]));
- sc->sc_rxdmadesc[idx].paddr = sc->sc_dma_base + rxs->segment.ds_addr;
+ sc->sc_rxdmadesc[idx].paddr = glc_map_addr(sc, rxs->segment.ds_addr);
sc->sc_rxdmadesc[idx].len = rxs->segment.ds_len;
- sc->sc_rxdmadesc[idx].next = sc->sc_dma_base + sc->sc_rxdmadesc_phys +
- ((idx + 1) % GLC_MAX_RX_PACKETS)*sizeof(sc->sc_rxdmadesc[idx]);
+ sc->sc_rxdmadesc[idx].next = glc_map_addr(sc, sc->sc_rxdmadesc_phys +
+ ((idx + 1) % GLC_MAX_RX_PACKETS)*sizeof(sc->sc_rxdmadesc[idx]));
sc->sc_rxdmadesc[idx].cmd_stat = GELIC_DESCR_OWNED;
rxs->rxs_desc_slot = idx;
- rxs->rxs_desc = sc->sc_dma_base + sc->sc_rxdmadesc_phys +
- idx*sizeof(struct glc_dmadesc);
+ rxs->rxs_desc = glc_map_addr(sc, sc->sc_rxdmadesc_phys +
+ idx*sizeof(struct glc_dmadesc));
return (0);
}
@@ -544,19 +573,19 @@ glc_encap(struct glc_softc *sc, struct m
txs->txs_firstdesc = sc->next_txdma_slot;
idx = txs->txs_firstdesc;
- firstslotphys = sc->sc_dma_base + sc->sc_txdmadesc_phys +
- txs->txs_firstdesc*sizeof(struct glc_dmadesc);
+ firstslotphys = glc_map_addr(sc, sc->sc_txdmadesc_phys +
+ txs->txs_firstdesc*sizeof(struct glc_dmadesc));
for (i = 0; i < nsegs; i++) {
if (i+1 == nsegs)
txs->txs_lastdesc = sc->next_txdma_slot;
bzero(&sc->sc_txdmadesc[idx], sizeof(sc->sc_txdmadesc[idx]));
- sc->sc_txdmadesc[idx].paddr = sc->sc_dma_base + segs[i].ds_addr;
+ sc->sc_txdmadesc[idx].paddr = glc_map_addr(sc, segs[i].ds_addr);
sc->sc_txdmadesc[idx].len = segs[i].ds_len;
- sc->sc_txdmadesc[idx].next = sc->sc_dma_base +
+ sc->sc_txdmadesc[idx].next = glc_map_addr(sc,
sc->sc_txdmadesc_phys +
- ((idx + 1) % GLC_MAX_TX_PACKETS)*sizeof(struct glc_dmadesc);
+ ((idx + 1) % GLC_MAX_TX_PACKETS)*sizeof(struct glc_dmadesc));
sc->sc_txdmadesc[idx].cmd_stat |= GELIC_CMDSTAT_NOIPSEC;
if (i+1 == nsegs) {
Modified: user/nwhitehorn/ps3/powerpc/ps3/if_glcreg.h
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/if_glcreg.h Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/ps3/if_glcreg.h Wed Sep 1 17:02:31 2010 (r212101)
@@ -70,7 +70,7 @@ struct glc_softc {
int sc_tx_vlan, sc_rx_vlan;
int sc_ifpflags;
- uint64_t sc_dma_base;
+ uint64_t sc_dma_base[5];
bus_dma_tag_t sc_dmadesc_tag;
int sc_irqid;
Modified: user/nwhitehorn/ps3/powerpc/ps3/mmu_ps3.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/mmu_ps3.c Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/ps3/mmu_ps3.c Wed Sep 1 17:02:31 2010 (r212101)
@@ -264,7 +264,7 @@ mps3_pte_insert(u_int ptegidx, struct lp
if (result != 0) {
/* No freeable slots in either PTEG? We're hosed. */
- mtmsr(mfmsr() | PSL_DR); panic("moea64_pte_insert: overflow");
+ panic("mps3_pte_insert: overflow (%d)", result);
return (-1);
}
Modified: user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c Wed Sep 1 16:53:38 2010 (r212100)
+++ user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c Wed Sep 1 17:02:31 2010 (r212101)
@@ -62,6 +62,7 @@ static int ps3_probe(platform_t);
static int ps3_attach(platform_t);
static void ps3_mem_regions(platform_t, struct mem_region **phys, int *physsz,
struct mem_region **avail, int *availsz);
+static vm_offset_t ps3_real_maxaddr(platform_t);
static u_long ps3_timebase_freq(platform_t, struct cpuref *cpuref);
static int ps3_smp_first_cpu(platform_t, struct cpuref *cpuref);
static int ps3_smp_next_cpu(platform_t, struct cpuref *cpuref);
@@ -73,6 +74,7 @@ static platform_method_t ps3_methods[] =
PLATFORMMETHOD(platform_probe, ps3_probe),
PLATFORMMETHOD(platform_attach, ps3_attach),
PLATFORMMETHOD(platform_mem_regions, ps3_mem_regions),
+ PLATFORMMETHOD(platform_real_maxaddr, ps3_real_maxaddr),
PLATFORMMETHOD(platform_timebase_freq, ps3_timebase_freq),
PLATFORMMETHOD(platform_smp_first_cpu, ps3_smp_first_cpu),
@@ -114,34 +116,48 @@ ps3_probe(platform_t plat)
#endif
}
+#define MEM_REGIONS 2
+static struct mem_region avail_regions[MEM_REGIONS];
+
static int
ps3_attach(platform_t plat)
{
+ uint64_t lpar_id, junk, ppe_id;
+
+ /* Get real mode memory region */
+ avail_regions[0].mr_start = 0;
+ lv1_get_logical_partition_id(&lpar_id);
+ lv1_get_logical_ppe_id(&ppe_id);
+ lv1_get_repository_node_value(lpar_id,
+ lv1_repository_string("bi") >> 32, lv1_repository_string("pu"),
+ ppe_id, lv1_repository_string("rm_size"),
+ &avail_regions[0].mr_size, &junk);
+
+ /* Now get extended memory region */
+ lv1_get_repository_node_value(lpar_id,
+ lv1_repository_string("bi") >> 32,
+ lv1_repository_string("rgntotal"), 0, 0,
+ &avail_regions[1].mr_size, &junk);
+
+ /* Convert to maximum amount we can allocate in 16 MB pages */
+ avail_regions[1].mr_size -= avail_regions[0].mr_size;
+ avail_regions[1].mr_size -= avail_regions[1].mr_size % (16*1024*1024);
+
+ lv1_allocate_memory(avail_regions[1].mr_size, 24 /* 16 MB pages */,
+ 0, 0x04 /* any address */, &avail_regions[1].mr_start, &junk);
pmap_mmu_install("mmu_ps3", BUS_PROBE_SPECIFIC);
return (0);
}
-#define MEM_REGIONS 8
-static struct mem_region avail_regions[MEM_REGIONS];
-
void
ps3_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
struct mem_region **avail, int *availsz)
{
- uint64_t lpar_id, junk, ppe_id;
-
- avail_regions[0].mr_start = 0;
- lv1_get_logical_partition_id(&lpar_id);
- lv1_get_logical_ppe_id(&ppe_id);
- lv1_get_repository_node_value(lpar_id,
- lv1_repository_string("bi") >> 32, lv1_repository_string("pu"),
- ppe_id, lv1_repository_string("rm_size"),
- &avail_regions[0].mr_size, &junk);
*phys = *avail = avail_regions;
- *physsz = *availsz = 1;
+ *physsz = *availsz = MEM_REGIONS;
}
static u_long
@@ -223,3 +239,10 @@ ps3_reset(platform_t plat)
{
lv1_panic(1);
}
+
+static vm_offset_t
+ps3_real_maxaddr(platform_t plat)
+{
+ return (avail_regions[0].mr_start + avail_regions[0].mr_size);
+}
+
More information about the svn-src-user
mailing list