summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-14 14:08:45 +0000
committerian <ian@FreeBSD.org>2014-05-14 14:08:45 +0000
commit796f2c87ad85df08fa64cd699bc66b9054363166 (patch)
tree47b4dd928c54ad5a9bb1ca1738555cad170af43d /sys/powerpc
parentdeadfc3726d811669f361da8003352165638c410 (diff)
downloadFreeBSD-src-796f2c87ad85df08fa64cd699bc66b9054363166.zip
FreeBSD-src-796f2c87ad85df08fa64cd699bc66b9054363166.tar.gz
MFC r258268, r258271, r258272, r258274, r258275, r258427, r258694, r258696,
r258697, r258757 Do not assume a value for #address-cells when parsing the OF translations map. This allows the kernel to get farther with OpenBIOS on 64-bit CPUs. Actually look up #address-cells instead of assuming it is correlated with the Uninorth version number. #interrupt-cells belongs to the iparent, not the device parent. Add a sysctl to allow disabling resetting the OF syscons. For PCI<->PCI bridges, #address-cells may be 3. Make RTAS calls, which call setfault() to recover from machine checks, preserve any existing fault buffer. badaddr() is used only in the grackle PCI driver, so move its definition there. Clean up a spurious setfault() declaration as well. This [phyp_console] driver doesn't need the /options node, so don't check for it. Use the Open Firmware-based CPU frequency determination as a generic fallback if we can't measure CPU frequency. This is also useful on a variety of embedded systems using FDT.
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/aim/machdep.c2
-rw-r--r--sys/powerpc/aim/mmu_oea64.c44
-rw-r--r--sys/powerpc/aim/trap.c59
-rw-r--r--sys/powerpc/booke/trap.c60
-rw-r--r--sys/powerpc/ofw/ofw_syscons.c41
-rw-r--r--sys/powerpc/powermac/grackle.c50
-rw-r--r--sys/powerpc/powermac/macio.c8
-rw-r--r--sys/powerpc/powermac/uninorth.c20
-rw-r--r--sys/powerpc/powermac/uninorthpci.c20
-rw-r--r--sys/powerpc/powermac/uninorthvar.h4
-rw-r--r--sys/powerpc/pseries/phyp_console.c4
11 files changed, 133 insertions, 179 deletions
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 72f9de7..c4c7383 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -159,8 +159,6 @@ SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
uintptr_t powerpc_init(vm_offset_t, vm_offset_t, vm_offset_t, void *);
-int setfault(faultbuf); /* defined in locore.S */
-
long Maxmem = 0;
long realmem = 0;
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index 0669f66..b47b94d 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -180,8 +180,7 @@ uintptr_t moea64_get_unique_vsid(void);
struct ofw_map {
cell_t om_va;
cell_t om_len;
- cell_t om_pa_hi;
- cell_t om_pa_lo;
+ uint64_t om_pa;
cell_t om_mode;
};
@@ -471,13 +470,9 @@ om_cmp(const void *a, const void *b)
mapa = a;
mapb = b;
- if (mapa->om_pa_hi < mapb->om_pa_hi)
+ if (mapa->om_pa < mapb->om_pa)
return (-1);
- else if (mapa->om_pa_hi > mapb->om_pa_hi)
- return (1);
- else if (mapa->om_pa_lo < mapb->om_pa_lo)
- return (-1);
- else if (mapa->om_pa_lo > mapb->om_pa_lo)
+ else if (mapa->om_pa > mapb->om_pa)
return (1);
else
return (0);
@@ -486,26 +481,41 @@ om_cmp(const void *a, const void *b)
static void
moea64_add_ofw_mappings(mmu_t mmup, phandle_t mmu, size_t sz)
{
- struct ofw_map translations[sz/sizeof(struct ofw_map)];
+ struct ofw_map translations[sz/(4*sizeof(cell_t))]; /*>= 4 cells per */
+ pcell_t acells, trans_cells[sz/sizeof(cell_t)];
register_t msr;
vm_offset_t off;
vm_paddr_t pa_base;
- int i;
+ int i, j;
bzero(translations, sz);
- if (OF_getprop(mmu, "translations", translations, sz) == -1)
+ OF_getprop(OF_finddevice("/"), "#address-cells", &acells,
+ sizeof(acells));
+ if (OF_getprop(mmu, "translations", trans_cells, sz) == -1)
panic("moea64_bootstrap: can't get ofw translations");
CTR0(KTR_PMAP, "moea64_add_ofw_mappings: translations");
- sz /= sizeof(*translations);
+ sz /= sizeof(cell_t);
+ for (i = 0, j = 0; i < sz; j++) {
+ translations[j].om_va = trans_cells[i++];
+ translations[j].om_len = trans_cells[i++];
+ translations[j].om_pa = trans_cells[i++];
+ if (acells == 2) {
+ translations[j].om_pa <<= 32;
+ translations[j].om_pa |= trans_cells[i++];
+ }
+ translations[j].om_mode = trans_cells[i++];
+ }
+ KASSERT(i == sz, ("Translations map has incorrect cell count (%d/%zd)",
+ i, sz));
+
+ sz = j;
qsort(translations, sz, sizeof (*translations), om_cmp);
for (i = 0; i < sz; i++) {
- pa_base = translations[i].om_pa_lo;
- #ifdef __powerpc64__
- pa_base += (vm_offset_t)translations[i].om_pa_hi << 32;
- #else
- if (translations[i].om_pa_hi)
+ pa_base = translations[i].om_pa;
+ #ifndef __powerpc64__
+ if ((translations[i].om_pa >> 32) != 0)
panic("OFW translations above 32-bit boundary!");
#endif
diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c
index 025b5cf..055603c 100644
--- a/sys/powerpc/aim/trap.c
+++ b/sys/powerpc/aim/trap.c
@@ -89,12 +89,6 @@ static int handle_user_slb_spill(pmap_t pm, vm_offset_t addr);
extern int n_slbs;
#endif
-int setfault(faultbuf); /* defined in locore.S */
-
-/* Why are these not defined in a header? */
-int badaddr(void *, size_t);
-int badaddr_read(void *, size_t, int *);
-
struct powerpc_exception {
u_int vector;
char *name;
@@ -695,59 +689,6 @@ trap_pfault(struct trapframe *frame, int user)
return (SIGSEGV);
}
-int
-badaddr(void *addr, size_t size)
-{
- return (badaddr_read(addr, size, NULL));
-}
-
-int
-badaddr_read(void *addr, size_t size, int *rptr)
-{
- struct thread *td;
- faultbuf env;
- int x;
-
- /* Get rid of any stale machine checks that have been waiting. */
- __asm __volatile ("sync; isync");
-
- td = curthread;
-
- if (setfault(env)) {
- td->td_pcb->pcb_onfault = 0;
- __asm __volatile ("sync");
- return 1;
- }
-
- __asm __volatile ("sync");
-
- switch (size) {
- case 1:
- x = *(volatile int8_t *)addr;
- break;
- case 2:
- x = *(volatile int16_t *)addr;
- break;
- case 4:
- x = *(volatile int32_t *)addr;
- break;
- default:
- panic("badaddr: invalid size (%zd)", size);
- }
-
- /* Make sure we took the machine check, if we caused one. */
- __asm __volatile ("sync; isync");
-
- td->td_pcb->pcb_onfault = 0;
- __asm __volatile ("sync"); /* To be sure. */
-
- /* Use the value to avoid reorder. */
- if (rptr)
- *rptr = x;
-
- return (0);
-}
-
/*
* For now, this only deals with the particular unaligned access case
* that gcc tends to generate. Eventually it should handle all of the
diff --git a/sys/powerpc/booke/trap.c b/sys/powerpc/booke/trap.c
index dc84ede..476f77f 100644
--- a/sys/powerpc/booke/trap.c
+++ b/sys/powerpc/booke/trap.c
@@ -87,12 +87,6 @@ static int fix_unaligned(struct thread *td, struct trapframe *frame);
static int handle_onfault(struct trapframe *frame);
static void syscall(struct trapframe *frame);
-int setfault(faultbuf); /* defined in locore.S */
-
-/* Why are these not defined in a header? */
-int badaddr(void *, size_t);
-int badaddr_read(void *, size_t, int *);
-
struct powerpc_exception {
u_int vector;
char *name;
@@ -461,60 +455,6 @@ trap_pfault(struct trapframe *frame, int user)
return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
}
-int
-badaddr(void *addr, size_t size)
-{
-
- return (badaddr_read(addr, size, NULL));
-}
-
-int
-badaddr_read(void *addr, size_t size, int *rptr)
-{
- struct thread *td;
- faultbuf env;
- int x;
-
- /* Get rid of any stale machine checks that have been waiting. */
- __asm __volatile ("sync; isync");
-
- td = curthread;
-
- if (setfault(env)) {
- td->td_pcb->pcb_onfault = 0;
- __asm __volatile ("sync");
- return (1);
- }
-
- __asm __volatile ("sync");
-
- switch (size) {
- case 1:
- x = *(volatile int8_t *)addr;
- break;
- case 2:
- x = *(volatile int16_t *)addr;
- break;
- case 4:
- x = *(volatile int32_t *)addr;
- break;
- default:
- panic("badaddr: invalid size (%d)", size);
- }
-
- /* Make sure we took the machine check, if we caused one. */
- __asm __volatile ("sync; isync");
-
- td->td_pcb->pcb_onfault = 0;
- __asm __volatile ("sync"); /* To be sure. */
-
- /* Use the value to avoid reorder. */
- if (rptr)
- *rptr = x;
-
- return (0);
-}
-
/*
* For now, this only deals with the particular unaligned access case
* that gcc tends to generate. Eventually it should handle all of the
diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c
index bee9672..a8797c2 100644
--- a/sys/powerpc/ofw/ofw_syscons.c
+++ b/sys/powerpc/ofw/ofw_syscons.c
@@ -57,9 +57,12 @@ __FBSDID("$FreeBSD$");
#include <powerpc/ofw/ofw_syscons.h>
static int ofwfb_ignore_mmap_checks = 1;
+static int ofwfb_reset_on_switch = 1;
static SYSCTL_NODE(_hw, OID_AUTO, ofwfb, CTLFLAG_RD, 0, "ofwfb");
SYSCTL_INT(_hw_ofwfb, OID_AUTO, relax_mmap, CTLFLAG_RW,
&ofwfb_ignore_mmap_checks, 0, "relaxed mmap bounds checking");
+SYSCTL_INT(_hw_ofwfb, OID_AUTO, reset_on_mode_switch, CTLFLAG_RW,
+ &ofwfb_reset_on_switch, 0, "reset the framebuffer driver on mode switch");
extern u_char dflt_font_16[];
extern u_char dflt_font_14[];
@@ -447,26 +450,28 @@ ofwfb_set_mode(video_adapter_t *adp, int mode)
sc = (struct ofwfb_softc *)adp;
- /*
- * Open the display device, which will initialize it.
- */
-
- memset(name, 0, sizeof(name));
- OF_package_to_path(sc->sc_node, name, sizeof(name));
- ih = OF_open(name);
-
- if (sc->sc_depth == 8) {
+ if (ofwfb_reset_on_switch) {
/*
- * Install the ISO6429 colormap - older OFW systems
- * don't do this by default
+ * Open the display device, which will initialize it.
*/
- for (i = 0; i < 16; i++) {
- OF_call_method("color!", ih, 4, 1,
- ofwfb_cmap[i].red,
- ofwfb_cmap[i].green,
- ofwfb_cmap[i].blue,
- i,
- &retval);
+
+ memset(name, 0, sizeof(name));
+ OF_package_to_path(sc->sc_node, name, sizeof(name));
+ ih = OF_open(name);
+
+ if (sc->sc_depth == 8) {
+ /*
+ * Install the ISO6429 colormap - older OFW systems
+ * don't do this by default
+ */
+ for (i = 0; i < 16; i++) {
+ OF_call_method("color!", ih, 4, 1,
+ ofwfb_cmap[i].red,
+ ofwfb_cmap[i].green,
+ ofwfb_cmap[i].blue,
+ i,
+ &retval);
+ }
}
}
diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c
index ddb7f70..03c975d 100644
--- a/sys/powerpc/powermac/grackle.c
+++ b/sys/powerpc/powermac/grackle.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
@@ -59,8 +60,6 @@ __FBSDID("$FreeBSD$");
#include "pcib_if.h"
-int badaddr(void *, size_t); /* XXX */
-
/*
* Device interface.
*/
@@ -81,6 +80,9 @@ static void grackle_write_config(device_t, u_int, u_int, u_int,
static int grackle_enable_config(struct grackle_softc *, u_int,
u_int, u_int, u_int);
static void grackle_disable_config(struct grackle_softc *);
+static int badaddr(void *, size_t);
+
+int setfault(faultbuf); /* defined in locore.S */
/*
* Driver methods.
@@ -238,6 +240,50 @@ grackle_disable_config(struct grackle_softc *sc)
out32rb(sc->sc_addr, 0);
}
+static int
+badaddr(void *addr, size_t size)
+{
+ struct thread *td;
+ faultbuf env, *oldfaultbuf;
+ int x;
+
+ /* Get rid of any stale machine checks that have been waiting. */
+ __asm __volatile ("sync; isync");
+
+ td = curthread;
+
+ oldfaultbuf = td->td_pcb->pcb_onfault;
+ if (setfault(env)) {
+ td->td_pcb->pcb_onfault = oldfaultbuf;
+ __asm __volatile ("sync");
+ return 1;
+ }
+
+ __asm __volatile ("sync");
+
+ switch (size) {
+ case 1:
+ x = *(volatile int8_t *)addr;
+ break;
+ case 2:
+ x = *(volatile int16_t *)addr;
+ break;
+ case 4:
+ x = *(volatile int32_t *)addr;
+ break;
+ default:
+ panic("badaddr: invalid size (%zd)", size);
+ }
+
+ /* Make sure we took the machine check, if we caused one. */
+ __asm __volatile ("sync; isync");
+
+ td->td_pcb->pcb_onfault = oldfaultbuf;
+ __asm __volatile ("sync"); /* To be sure. */
+
+ return (0);
+}
+
/*
* Driver to swallow Grackle host bridges from the PCI bus side.
*/
diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c
index 8a980ba..6a0b913 100644
--- a/sys/powerpc/powermac/macio.c
+++ b/sys/powerpc/powermac/macio.c
@@ -201,10 +201,6 @@ macio_add_intr(phandle_t devnode, struct macio_devinfo *dinfo)
return;
}
- if (OF_searchprop(devnode, "#interrupt-cells", &icells, sizeof(icells))
- <= 0)
- icells = 1;
-
nintr = OF_getprop_alloc(devnode, "interrupts", sizeof(*intr),
(void **)&intr);
if (nintr == -1) {
@@ -221,6 +217,10 @@ macio_add_intr(phandle_t devnode, struct macio_devinfo *dinfo)
<= 0)
panic("Interrupt but no interrupt parent!\n");
+ if (OF_getprop(OF_xref_phandle(iparent), "#interrupt-cells", &icells,
+ sizeof(icells)) <= 0)
+ icells = 1;
+
for (i = 0; i < nintr; i+=icells) {
u_int irq = MAP_IRQ(iparent, intr[i]);
diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c
index 7976a81..ab051a5 100644
--- a/sys/powerpc/powermac/uninorth.c
+++ b/sys/powerpc/powermac/uninorth.c
@@ -270,6 +270,7 @@ unin_chip_attach(device_t dev)
phandle_t child;
phandle_t iparent;
device_t cdev;
+ cell_t acells, scells;
char compat[32];
char name[32];
u_int irq, reg[3];
@@ -281,12 +282,21 @@ unin_chip_attach(device_t dev)
if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8)
return (ENXIO);
- if (strcmp(ofw_bus_get_name(dev), "u3") == 0
- || strcmp(ofw_bus_get_name(dev), "u4") == 0)
- i = 1; /* #address-cells lies */
+ acells = scells = 1;
+ OF_getprop(OF_parent(root), "#address-cells", &acells, sizeof(acells));
+ OF_getprop(OF_parent(root), "#size-cells", &scells, sizeof(scells));
- sc->sc_physaddr = reg[i];
- sc->sc_size = reg[i+1];
+ i = 0;
+ sc->sc_physaddr = reg[i++];
+ if (acells == 2) {
+ sc->sc_physaddr <<= 32;
+ sc->sc_physaddr |= reg[i++];
+ }
+ sc->sc_size = reg[i++];
+ if (scells == 2) {
+ sc->sc_size <<= 32;
+ sc->sc_size |= reg[i++];
+ }
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
sc->sc_mem_rman.rm_descr = "UniNorth Device Memory";
diff --git a/sys/powerpc/powermac/uninorthpci.c b/sys/powerpc/powermac/uninorthpci.c
index f55fb72..5cf7a79 100644
--- a/sys/powerpc/powermac/uninorthpci.c
+++ b/sys/powerpc/powermac/uninorthpci.c
@@ -134,7 +134,9 @@ uninorth_attach(device_t dev)
struct uninorth_softc *sc;
const char *compatible;
phandle_t node;
- u_int32_t reg[3];
+ uint32_t reg[3];
+ uint64_t regbase;
+ cell_t acells;
node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
@@ -149,14 +151,18 @@ uninorth_attach(device_t dev)
if (strcmp(compatible, "u4-pcie") == 0)
sc->sc_ver = 4;
- if (sc->sc_ver >= 3) {
- sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[1] + 0x800000, PAGE_SIZE);
- sc->sc_data = (vm_offset_t)pmap_mapdev(reg[1] + 0xc00000, PAGE_SIZE);
- } else {
- sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[0] + 0x800000, PAGE_SIZE);
- sc->sc_data = (vm_offset_t)pmap_mapdev(reg[0] + 0xc00000, PAGE_SIZE);
+ acells = 1;
+ OF_getprop(OF_parent(node), "#address-cells", &acells, sizeof(acells));
+
+ regbase = reg[0];
+ if (acells == 2) {
+ regbase <<= 32;
+ regbase |= reg[1];
}
+ sc->sc_addr = (vm_offset_t)pmap_mapdev(regbase + 0x800000, PAGE_SIZE);
+ sc->sc_data = (vm_offset_t)pmap_mapdev(regbase + 0xc00000, PAGE_SIZE);
+
return (ofw_pci_attach(dev));
}
diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h
index c99a11b..e08478d 100644
--- a/sys/powerpc/powermac/uninorthvar.h
+++ b/sys/powerpc/powermac/uninorthvar.h
@@ -40,9 +40,9 @@ struct uninorth_softc {
};
struct unin_chip_softc {
- u_int32_t sc_physaddr;
+ uint64_t sc_physaddr;
+ uint64_t sc_size;
vm_offset_t sc_addr;
- u_int32_t sc_size;
struct rman sc_mem_rman;
int sc_version;
};
diff --git a/sys/powerpc/pseries/phyp_console.c b/sys/powerpc/pseries/phyp_console.c
index 2434697..79d9094 100644
--- a/sys/powerpc/pseries/phyp_console.c
+++ b/sys/powerpc/pseries/phyp_console.c
@@ -192,11 +192,9 @@ uart_phyp_cnprobe(struct consdev *cp)
{
char buf[64];
ihandle_t stdout;
- phandle_t input, opts, chosen;
+ phandle_t input, chosen;
static struct uart_phyp_softc sc;
- if ((opts = OF_finddevice("/options")) == -1)
- goto fail;
if ((chosen = OF_finddevice("/chosen")) == -1)
goto fail;
OpenPOWER on IntegriCloud