Add a new ram0 pseudo-device that claims memory resouces for physical

addresses corresponding to system RAM.  On amd64 ram0 uses the SMAP
and claims all the type 1 SMAP regions.  On i386 ram0 uses the
dump_avail[] array.  Note that on i386 we have to ignore regions above
4G in PAE kernels since bus resources use longs.
This commit is contained in:
jhb 2007-03-20 21:08:39 +00:00
parent d7f955fd67
commit 9c3aae9403
2 changed files with 154 additions and 0 deletions

View File

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/linker.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <machine/bus.h>
@ -59,7 +60,9 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <machine/pmap.h>
#include <machine/metadata.h>
#include <machine/resource.h>
#include <machine/pc/bios.h>
#include "pcib_if.h"
@ -550,6 +553,79 @@ nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs)
return (msi_release(irqs, count));
}
/* Placeholder for system RAM. */
static void
ram_identify(driver_t *driver, device_t parent)
{
if (resource_disabled("ram", 0))
return;
if (BUS_ADD_CHILD(parent, 0, "ram", 0) == NULL)
panic("ram_identify");
}
static int
ram_probe(device_t dev)
{
device_quiet(dev);
device_set_desc(dev, "System RAM");
return (0);
}
static int
ram_attach(device_t dev)
{
struct bios_smap *smapbase, *smap, *smapend;
struct resource *res;
caddr_t kmdp;
uint32_t smapsize;
int error, rid;
/* Retrieve the system memory map from the loader. */
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
smapbase = (struct bios_smap *)preload_search_info(kmdp,
MODINFO_METADATA | MODINFOMD_SMAP);
smapsize = *((u_int32_t *)smapbase - 1);
smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
rid = 0;
for (smap = smapbase; smap < smapend; smap++) {
if (smap->type != 0x01 || smap->length == 0)
continue;
error = bus_set_resource(dev, SYS_RES_MEMORY, rid, smap->base,
smap->length);
if (error)
panic("ram_attach: resource %d failed set with %d", rid,
error);
res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
if (res == NULL)
panic("ram_attach: resource %d failed to attach", rid);
rid++;
}
return (0);
}
static device_method_t ram_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, ram_identify),
DEVMETHOD(device_probe, ram_probe),
DEVMETHOD(device_attach, ram_attach),
{ 0, 0 }
};
static driver_t ram_driver = {
"ram",
ram_methods,
1, /* no softc */
};
static devclass_t ram_devclass;
DRIVER_MODULE(ram, nexus, ram_driver, ram_devclass, 0, 0);
#ifdef DEV_ISA
/*
* Placeholder which claims PnP 'devices' which describe system

View File

@ -607,6 +607,84 @@ nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs)
}
#endif
/* Placeholder for system RAM. */
static void
ram_identify(driver_t *driver, device_t parent)
{
if (resource_disabled("ram", 0))
return;
if (BUS_ADD_CHILD(parent, 0, "ram", 0) == NULL)
panic("ram_identify");
}
static int
ram_probe(device_t dev)
{
device_quiet(dev);
device_set_desc(dev, "System RAM");
return (0);
}
static int
ram_attach(device_t dev)
{
struct resource *res;
vm_paddr_t *p;
int error, i, rid;
/*
* We use the dump_avail[] array rather than phys_avail[] for
* the memory map as phys_avail[] contains holes for kernel
* memory, page 0, the message buffer, and the dcons buffer.
* We test the end address in the loop instead of the start
* since the start address for the first segment is 0.
*
* XXX: It would be preferable to use the SMAP if it exists
* instead since if the SMAP is very fragmented we may not
* include some memory regions in dump_avail[] and phys_avail[].
*/
for (i = 0, p = dump_avail; p[1] != 0; i++, p += 2) {
rid = i;
#ifdef PAE
/*
* Resources use long's to track resources, so we can't
* include memory regions above 4GB.
*/
if (p[0] >= ~0ul)
break;
#endif
error = bus_set_resource(dev, SYS_RES_MEMORY, rid, p[0],
p[1] - p[0]);
if (error)
panic("ram_attach: resource %d failed set with %d", i,
error);
res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
if (res == NULL)
panic("ram_attach: resource %d failed to attach", i);
}
return (0);
}
static device_method_t ram_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, ram_identify),
DEVMETHOD(device_probe, ram_probe),
DEVMETHOD(device_attach, ram_attach),
{ 0, 0 }
};
static driver_t ram_driver = {
"ram",
ram_methods,
1, /* no softc */
};
static devclass_t ram_devclass;
DRIVER_MODULE(ram, nexus, ram_driver, ram_devclass, 0, 0);
#ifdef DEV_ISA
/*
* Placeholder which claims PnP 'devices' which describe system