summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2010-04-12 23:16:16 +0000
committerimp <imp@FreeBSD.org>2010-04-12 23:16:16 +0000
commit4db75e1a62c2f69f67a921c34d9be31dc951fe8d (patch)
tree0c8e1c9067a1556456275b0ec4337b5853bc5528
parent3c756540edb731191bace768a61a742408d850c1 (diff)
downloadFreeBSD-src-4db75e1a62c2f69f67a921c34d9be31dc951fe8d.zip
FreeBSD-src-4db75e1a62c2f69f67a921c34d9be31dc951fe8d.tar.gz
merge from head, part 10 of many
-rw-r--r--sys/mips/atheros/if_arge.c2
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_rgmx.c298
-rw-r--r--sys/mips/cavium/octeon_ebt3000_cf.c127
-rw-r--r--sys/mips/cavium/octeon_machdep.c27
-rw-r--r--sys/mips/cavium/octeon_pcmap_regs.h480
-rw-r--r--sys/mips/conf/AR71XX9
-rw-r--r--sys/mips/conf/OCTEON12
-rw-r--r--sys/mips/conf/OCTEON1-322
-rw-r--r--sys/mips/include/bus.h2
-rw-r--r--sys/mips/include/clock.h8
-rw-r--r--sys/mips/include/cpu.h14
-rw-r--r--sys/mips/include/cpufunc.h29
-rw-r--r--sys/mips/include/cpuregs.h8
-rw-r--r--sys/mips/include/db_machdep.h1
-rw-r--r--sys/mips/include/kdb.h2
-rw-r--r--sys/mips/include/param.h11
-rw-r--r--sys/mips/include/pmap.h5
-rw-r--r--sys/mips/include/smp.h4
-rw-r--r--sys/mips/include/trap.h3
-rw-r--r--sys/mips/mips/busdma_machdep.c11
-rw-r--r--sys/mips/mips/db_trace.c21
-rw-r--r--sys/mips/mips/exception.S327
-rw-r--r--sys/mips/mips/mp_machdep.c15
-rw-r--r--sys/mips/mips/nexus.c1
-rw-r--r--sys/mips/mips/pm_machdep.c8
-rw-r--r--sys/mips/mips/pmap.c213
-rw-r--r--sys/mips/mips/support.S108
-rw-r--r--sys/mips/mips/swtch.S8
-rw-r--r--sys/mips/mips/tick.c58
-rw-r--r--sys/mips/mips/trap.c8
-rw-r--r--sys/mips/mips/vm_machdep.c20
-rw-r--r--sys/mips/sibyte/sb_asm.S50
-rw-r--r--sys/mips/sibyte/sb_machdep.c30
-rw-r--r--sys/mips/sibyte/sb_scd.c20
-rw-r--r--sys/mips/sibyte/sb_scd.h1
35 files changed, 1058 insertions, 875 deletions
diff --git a/sys/mips/atheros/if_arge.c b/sys/mips/atheros/if_arge.c
index da8d181..4367bfb 100644
--- a/sys/mips/atheros/if_arge.c
+++ b/sys/mips/atheros/if_arge.c
@@ -171,7 +171,7 @@ extern uint32_t ar711_base_mac[ETHER_ADDR_LEN];
static struct mtx miibus_mtx;
-MTX_SYSINIT(miibus_mtx, &miibus_mtx, "arge mii lock", MTX_SPIN);
+MTX_SYSINIT(miibus_mtx, &miibus_mtx, "arge mii lock", MTX_DEF);
/*
diff --git a/sys/mips/cavium/dev/rgmii/octeon_rgmx.c b/sys/mips/cavium/dev/rgmii/octeon_rgmx.c
index 53365cc..ada0946 100644
--- a/sys/mips/cavium/dev/rgmii/octeon_rgmx.c
+++ b/sys/mips/cavium/dev/rgmii/octeon_rgmx.c
@@ -136,7 +136,6 @@ struct rgmx_softc_dev {
u_int idx;
u_char ieee[6];
- char const * typestr; /* printable name of the interface. */
u_short txb_size; /* size of TX buffer, in bytes */
/* Transmission buffer management. */
@@ -182,7 +181,6 @@ static u_int get_rgmx_port_ordinal(u_int port);
static void octeon_rgmx_set_mac(u_int port);
static void octeon_rgmx_init_sc(struct rgmx_softc_dev *sc, device_t dev, u_int port, u_int num_devices);
static int octeon_rgmx_init_ifnet(struct rgmx_softc_dev *sc);
-static void octeon_rgmx_mark_ready(struct rgmx_softc_dev *sc);
static void octeon_rgmx_stop(struct rgmx_softc_dev *sc);
static void octeon_rgmx_config_speed(u_int port, u_int);
#ifdef DEBUG_RGMX_DUMP
@@ -211,6 +209,7 @@ static int octeon_rgmx_intr(void *arg);
/* Standard driver entry points. These can be static. */
static void octeon_rgmx_init (void *);
//static driver_intr_t rgmx_intr;
+static void octeon_rgmx_config_cam (struct ifnet *);
static int octeon_rgmx_ioctl (struct ifnet *, u_long, caddr_t);
static void octeon_rgmx_output_start (struct ifnet *);
static void octeon_rgmx_output_start_locked (struct ifnet *);
@@ -349,8 +348,6 @@ static int octeon_rgmx_init_ifnet (struct rgmx_softc_dev *sc)
ifmedia_set(&sc->media, bit2media[0]);
ether_ifattach(sc->ifp, sc->ieee);
- /* Print additional info when attached. */
- device_printf(sc->sc_dev, "type %s, full duplex\n", sc->typestr);
return (0);
}
@@ -447,12 +444,6 @@ static int rgmii_attach (device_t dev)
device_printf(dev, " ifinit failed for rgmx port %u\n", port);
return (ENOSPC);
}
-/*
- * Don't call octeon_rgmx_mark_ready()
- * ifnet will call it indirectly via octeon_rgmx_init()
- *
- * octeon_rgmx_mark_ready(sc);
- */
num_devices++;
}
}
@@ -1024,10 +1015,9 @@ static u_int octeon_rgmx_pko_xmit_packet (struct rgmx_softc_dev *sc, void *out_b
* 3 words or less are left. We write our 2nd word now and then put in a chain link
* to new PKO cmd buf.
*/
- void *pko_cmd_buf = octeon_fpa_alloc(OCTEON_FPA_TX_CMDBUF_POOL);
- uint64_t phys_cmd_buf;
+ uint64_t phys_cmd_buf = octeon_fpa_alloc_phys(OCTEON_FPA_TX_CMDBUF_POOL);
- if (!pko_cmd_buf) {
+ if (!phys_cmd_buf) {
/*
* FPA pool for xmit-buffer-commands is empty.
*/
@@ -1035,7 +1025,6 @@ static u_int octeon_rgmx_pko_xmit_packet (struct rgmx_softc_dev *sc, void *out_b
octeon_spinlock_unlock(&(sc->outq_ptr[queue].lock));
return (0);
}
- phys_cmd_buf = OCTEON_PTR2PHYS(pko_cmd_buf);
xmit_cmd_ptr[1] = pko_pkt_word.word64;
xmit_cmd_ptr[2] = phys_cmd_buf;
@@ -1235,6 +1224,8 @@ static void octeon_rgmx_output_start_locked (struct ifnet *ifp)
for (ii = 0; ii < len; ii++) printf(" %X", dc[ii]); printf("\n");
#endif
+ ETHER_BPF_MTAP(ifp, m);
+
IF_ENQUEUE(&sc->tx_pending_queue, m);
/*
@@ -1648,9 +1639,106 @@ static int octeon_rgmx_medchange (struct ifnet *ifp)
static void octeon_rgmx_medstat (struct ifnet *ifp, struct ifmediareq *ifm)
{
- /*
- * No support for Media Status callback
- */
+ struct rgmx_softc_dev *sc = ifp->if_softc;
+ octeon_rgmx_rxx_rx_inbnd_t link_status;
+
+ octeon_rgmx_config_speed(sc->port, 1);
+
+ RGMX_LOCK(sc);
+
+ ifm->ifm_status = IFM_AVALID;
+ ifm->ifm_active = IFM_ETHER;
+
+ /*
+ * Parse link status.
+ */
+ link_status.word64 = sc->link_status;
+
+ if (!link_status.bits.status) {
+ RGMX_UNLOCK(sc);
+ return;
+ }
+
+ ifm->ifm_status |= IFM_ACTIVE;
+
+ switch (link_status.bits.speed) {
+ case 0:
+ ifm->ifm_active |= IFM_10_T;
+ break;
+ case 1:
+ ifm->ifm_active |= IFM_100_TX;
+ break;
+ case 2:
+ ifm->ifm_active |= IFM_1000_T;;
+ break;
+ default:
+ /* Unknown! */
+ break;
+ }
+
+ /*
+ * Check duplex.
+ */
+ if (link_status.bits.duplex == 1)
+ ifm->ifm_active |= IFM_FDX;
+ else
+ ifm->ifm_active |= IFM_HDX;
+
+ RGMX_UNLOCK(sc);
+}
+
+static void octeon_rgmx_config_cam(struct ifnet *ifp)
+{
+ struct rgmx_softc_dev *sc = ifp->if_softc;
+ u_int port = sc->port;
+ int index = INDEX(port);
+ int iface = INTERFACE(port);
+ u_int last_enabled;
+ uint64_t adr_ctl;
+
+ last_enabled = octeon_rgmx_stop_port(port);
+
+ adr_ctl = oct_read64(OCTEON_RGMX_RXX_ADR_CTL(index, iface));
+
+ /*
+ * Always accept broadcast traffic.
+ */
+ if ((adr_ctl & OCTEON_RGMX_ADRCTL_ACCEPT_BROADCAST) == 0)
+ adr_ctl |= OCTEON_RGMX_ADRCTL_ACCEPT_BROADCAST;
+
+ /*
+ * Accept all multicast in all multicast mode and in
+ * promiscuous mode.
+ *
+ * XXX Since we don't handle programming the CAM for
+ * multicast filtering, always accept all multicast.
+ */
+ adr_ctl &= ~OCTEON_RGMX_ADRCTL_REJECT_ALL_MULTICAST;
+ adr_ctl |= OCTEON_RGMX_ADRCTL_ACCEPT_ALL_MULTICAST;
+
+ /*
+ * In promiscuous mode, the CAM is shut off, so reject everything.
+ * Otherwise, filter using the CAM.
+ */
+ if ((ifp->if_flags & IFF_PROMISC) != 0) {
+ adr_ctl &= ~OCTEON_RGMX_ADRCTL_CAM_MODE_ACCEPT_DMAC;
+ adr_ctl |= OCTEON_RGMX_ADRCTL_CAM_MODE_REJECT_DMAC;
+ } else {
+ adr_ctl &= ~OCTEON_RGMX_ADRCTL_CAM_MODE_REJECT_DMAC;
+ adr_ctl |= OCTEON_RGMX_ADRCTL_CAM_MODE_ACCEPT_DMAC;
+ }
+
+ oct_write64(OCTEON_RGMX_RXX_ADR_CTL(index, iface), adr_ctl);
+
+ /*
+ * If in promiscuous mode, disable the CAM.
+ */
+ if ((ifp->if_flags & IFF_PROMISC) != 0)
+ oct_write64(OCTEON_RGMX_RXX_ADR_CAM_EN(index, iface), 0);
+ else
+ oct_write64(OCTEON_RGMX_RXX_ADR_CAM_EN(index, iface), 1);
+
+ if (last_enabled) octeon_rgmx_start_port(port);
}
static int octeon_rgmx_ioctl (struct ifnet * ifp, u_long command, caddr_t data)
@@ -1671,28 +1759,21 @@ static int octeon_rgmx_ioctl (struct ifnet * ifp, u_long command, caddr_t data)
* "stopped", reflecting the UP flag.
*/
if (ifp->if_flags & IFF_UP) {
-
-
/*
* New state is IFF_UP
* Restart or Start now, if driver is not running currently.
*/
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- printf(" SIOCSTIFFLAGS UP/Not-running\n"); break;
octeon_rgmx_init(sc);
- } else {
- printf(" SIOCSTIFFLAGS UP/Running\n"); break;
}
+ octeon_rgmx_config_cam(ifp);
} else {
/*
* New state is IFF_DOWN.
* Stop & shut it down now, if driver is running currently.
*/
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
- printf(" SIOCSTIFFLAGS Down/Running\n"); break;
octeon_rgmx_stop(sc);
- } else {
- printf(" SIOCSTIFFLAGS Down/Not-Running\n"); break;
}
}
break;
@@ -1734,17 +1815,9 @@ static int octeon_rgmx_ioctl (struct ifnet * ifp, u_long command, caddr_t data)
return (error);
}
-
-
-
-/*
- * octeon_rgmx_mark_ready
- *
- * Initialize the rgmx driver for this instance
- * Initialize device.
- */
-static void octeon_rgmx_mark_ready (struct rgmx_softc_dev *sc)
+static void octeon_rgmx_init (void *xsc)
{
+ struct rgmx_softc_dev *sc = xsc;
/* Enable interrupts. */
/* For RGMX they are already enabled earlier */
@@ -1763,21 +1836,9 @@ static void octeon_rgmx_mark_ready (struct rgmx_softc_dev *sc)
/* Kick start the output */
/* Hopefully PKO is running and will pick up packets via the timer or receive loop */
-}
-
-static void octeon_rgmx_init (void *xsc)
-{
-
- /*
- * Called mostly from ifnet interface ifp->if_init();
- * I think we can anchor most of our iniialization here and
- * not do it in different places from driver_attach().
- */
- /*
- * For now, we only mark the interface ready
- */
- octeon_rgmx_mark_ready((struct rgmx_softc_dev *) xsc);
+ /* Set link status. */
+ octeon_rgmx_config_speed(sc->port, 1);
}
@@ -1792,7 +1853,6 @@ static void octeon_rgmx_config_speed (u_int port, u_int report_link)
uint64_t val64_tx_clk, val64_tx_slot, val64_tx_burst;
u_int last_enabled;
-
sc = get_rgmx_softc(port);
if (!sc) {
printf(" config_speed didn't find sc int:%u port:%u", iface, port);
@@ -1804,79 +1864,96 @@ static void octeon_rgmx_config_speed (u_int port, u_int report_link)
*/
link_status.word64 = oct_read64(OCTEON_RGMX_RXX_RX_INBND(index, iface));
+ RGMX_LOCK(sc);
+
/*
* Compre to prev known state. If same then nothing to do.
*/
if (link_status.word64 == sc->link_status) {
+ RGMX_UNLOCK(sc);
return;
}
-
- RGMX_LOCK(sc);
-
old_link_status.word64 = sc->link_status;
- sc->link_status = link_status.word64;
-
- last_enabled = octeon_rgmx_stop_port(port);
-
- gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, iface));
-
- /*
- * Duplex
- */
- gmx_cfg.bits.duplex = 1;
-
- switch (link_status.bits.speed) {
- case 0: /* 10Mbps */
- gmx_cfg.bits.speed = 0;
- gmx_cfg.bits.slottime = 0;
- val64_tx_clk = 50; val64_tx_slot = 0x40; val64_tx_burst = 0;
- break;
- case 1: /* 100Mbps */
- gmx_cfg.bits.speed = 0;
- gmx_cfg.bits.slottime = 0;
- val64_tx_clk = 5; val64_tx_slot = 0x40; val64_tx_burst = 0;
- break;
-
- case 2: /* 1Gbps */
- gmx_cfg.bits.speed = 1;
- gmx_cfg.bits.slottime = 1;
- val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
- break;
-
- case 3: /* ?? */
- default:
- gmx_cfg.bits.speed = 1;
- gmx_cfg.bits.slottime = 1;
- val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
- break;
- }
+ /*
+ * Compare to previous state modulo link status. If only link
+ * status is different, we don't need to change media.
+ */
+ if (old_link_status.bits.duplex != link_status.bits.duplex ||
+ old_link_status.bits.speed != link_status.bits.speed) {
+ last_enabled = octeon_rgmx_stop_port(port);
+
+ gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, iface));
- oct_write64(OCTEON_RGMX_TXX_CLK(index, iface), val64_tx_clk);
- oct_write64(OCTEON_RGMX_TXX_SLOT(index, iface), val64_tx_slot);
- oct_write64(OCTEON_RGMX_TXX_BURST(index, iface), val64_tx_burst);
+ /*
+ * Duplex
+ * XXX Set based on link_status.bits.duplex?
+ */
+ gmx_cfg.bits.duplex = 1;
+
+ switch (link_status.bits.speed) {
+ case 0: /* 10Mbps */
+ gmx_cfg.bits.speed = 0;
+ gmx_cfg.bits.slottime = 0;
+ val64_tx_clk = 50; val64_tx_slot = 0x40; val64_tx_burst = 0;
+ break;
+
+ case 1: /* 100Mbps */
+ gmx_cfg.bits.speed = 0;
+ gmx_cfg.bits.slottime = 0;
+ val64_tx_clk = 5; val64_tx_slot = 0x40; val64_tx_burst = 0;
+ break;
+
+ case 2: /* 1Gbps */
+ gmx_cfg.bits.speed = 1;
+ gmx_cfg.bits.slottime = 1;
+ val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
+ break;
+
+ case 3: /* ?? */
+ default:
+ gmx_cfg.bits.speed = 1;
+ gmx_cfg.bits.slottime = 1;
+ val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
+ break;
+ }
- oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64);
+ oct_write64(OCTEON_RGMX_TXX_CLK(index, iface), val64_tx_clk);
+ oct_write64(OCTEON_RGMX_TXX_SLOT(index, iface), val64_tx_slot);
+ oct_write64(OCTEON_RGMX_TXX_BURST(index, iface), val64_tx_burst);
+
+ oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64);
+
+ if (last_enabled) octeon_rgmx_start_port(port);
+ }
- if (last_enabled) octeon_rgmx_start_port(port);
+ /*
+ * Now check and possibly change link status.
+ */
+ if (link_status.bits.status != old_link_status.bits.status) {
+ if (report_link) {
+ if (link_status.bits.status) {
+ if_link_state_change(sc->ifp, LINK_STATE_UP);
+ } else {
+ if_link_state_change(sc->ifp, LINK_STATE_DOWN);
+ }
+ }
+ }
- if (link_status.bits.status != old_link_status.bits.status) {
+ if (report_link) {
+ sc->link_status = link_status.word64;
+ } else {
+ /*
+ * We can't update link status proper since we can't
+ * change it in the interface, so keep the old link
+ * status intact but note the current speed and duplex
+ * settings.
+ */
+ link_status.bits.status = old_link_status.bits.status;
+ sc->link_status = link_status.word64;
+ }
-//#define DEBUG_LINESTATUS
- if (link_status.bits.status) {
-#ifdef DEBUG_LINESTATUS
- printf(" %u/%u: Interface is now alive\n", iface, port);
-#endif
- if (report_link) if_link_state_change(sc->ifp, LINK_STATE_UP);
- } else {
-#ifdef DEBUG_LINESTATUS
- printf(" %u/%u: Interface went down\n", iface, port);
-#endif
- if (report_link) if_link_state_change(sc->ifp, LINK_STATE_DOWN);
- }
- }
RGMX_UNLOCK(sc);
-
}
@@ -2096,7 +2173,6 @@ static void octeon_config_rgmii_port (u_int port)
gmx_cfg.bits.en = 1;
oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64);
-
octeon_rgmx_config_speed(port, 0);
oct_write64(OCTEON_RGMX_TXX_THRESH(index, iface), 32);
@@ -2181,7 +2257,7 @@ static int octeon_has_4ports (void)
u_int chipid;
int retcode = 1;
- chipid = octeon_get_chipid() & 0xffffff00;
+ chipid = octeon_get_chipid();
switch (chipid) {
case OCTEON_CN31XX_CHIP:
diff --git a/sys/mips/cavium/octeon_ebt3000_cf.c b/sys/mips/cavium/octeon_ebt3000_cf.c
index 10fb313..4298b75 100644
--- a/sys/mips/cavium/octeon_ebt3000_cf.c
+++ b/sys/mips/cavium/octeon_ebt3000_cf.c
@@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
/* Status Register */
#define STATUS_BSY 0x80 /* Drive is busy */
#define STATUS_RDY 0x40 /* Drive is ready */
+#define STATUS_DF 0x20 /* Device fault */
#define STATUS_DRQ 0x08 /* Data can be transferred */
/* Miscelaneous */
@@ -153,11 +154,11 @@ static int cf_attach(device_t);
static int cf_attach_geom(void *, int);
/* ATA methods */
-static void cf_cmd_identify(void);
-static void cf_cmd_write(uint32_t, uint32_t, void *);
-static void cf_cmd_read(uint32_t, uint32_t, void *);
-static void cf_wait_busy(void);
-static void cf_send_cmd(uint32_t, uint8_t);
+static int cf_cmd_identify(void);
+static int cf_cmd_write(uint32_t, uint32_t, void *);
+static int cf_cmd_read(uint32_t, uint32_t, void *);
+static int cf_wait_busy(void);
+static int cf_send_cmd(uint32_t, uint8_t);
static void cf_attach_geom_proxy(void *arg, int flag);
/* Miscelenous */
@@ -183,6 +184,8 @@ static int cf_access (struct g_provider *pp, int r, int w, int e)
* ------------------------------------------------------------------- */
static void cf_start (struct bio *bp)
{
+ int error;
+
/*
* Handle actual I/O requests. The request is passed down through
* the bio struct.
@@ -200,12 +203,19 @@ static void cf_start (struct bio *bp)
if ((bp->bio_cmd & (BIO_READ | BIO_WRITE))) {
if (bp->bio_cmd & BIO_READ) {
- cf_cmd_read(bp->bio_length / drive_param.sector_size,
- bp->bio_offset / drive_param.sector_size, bp->bio_data);
-
+ error = cf_cmd_read(bp->bio_length / drive_param.sector_size,
+ bp->bio_offset / drive_param.sector_size, bp->bio_data);
} else if (bp->bio_cmd & BIO_WRITE) {
- cf_cmd_write(bp->bio_length / drive_param.sector_size,
- bp->bio_offset/drive_param.sector_size, bp->bio_data);
+ error = cf_cmd_write(bp->bio_length / drive_param.sector_size,
+ bp->bio_offset/drive_param.sector_size, bp->bio_data);
+ } else {
+ printf("%s: unrecognized bio_cmd %x.\n", __func__, bp->bio_cmd);
+ error = ENOTSUP;
+ }
+
+ if (error != 0) {
+ g_io_deliver(bp, error);
+ return;
}
bp->bio_resid = 0;
@@ -227,12 +237,13 @@ static int cf_ioctl (struct g_provider *pp, u_long cmd, void *data, int fflag, s
*
* Read nr_sectors from the device starting from start_sector.
*/
-static void cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf)
+static int cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf)
{
unsigned long lba;
uint32_t count;
uint16_t *ptr_16;
uint8_t *ptr_8;
+ int error;
//#define OCTEON_VISUAL_CF_0 1
#ifdef OCTEON_VISUAL_CF_0
@@ -244,8 +255,11 @@ static void cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf)
while (nr_sectors--) {
-
- cf_send_cmd(lba, CMD_READ_SECTOR);
+ error = cf_send_cmd(lba, CMD_READ_SECTOR);
+ if (error != 0) {
+ printf("%s: cf_send_cmd(CMD_READ_SECTOR) failed: %d\n", __func__, error);
+ return (error);
+ }
if (bus_width == 8) {
volatile uint8_t *task_file = (volatile uint8_t*)base_addr;
@@ -270,6 +284,7 @@ static void cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf)
#ifdef OCTEON_VISUAL_CF_0
octeon_led_write_char(0, ' ');
#endif
+ return (0);
}
@@ -279,12 +294,13 @@ static void cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf)
*
* Write nr_sectors to the device starting from start_sector.
*/
-static void cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
+static int cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
{
uint32_t lba;
uint32_t count;
uint16_t *ptr_16;
uint8_t *ptr_8;
+ int error;
//#define OCTEON_VISUAL_CF_1 1
#ifdef OCTEON_VISUAL_CF_1
@@ -295,8 +311,11 @@ static void cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
ptr_16 = (uint16_t*)buf;
while (nr_sectors--) {
-
- cf_send_cmd(lba, CMD_WRITE_SECTOR);
+ error = cf_send_cmd(lba, CMD_WRITE_SECTOR);
+ if (error != 0) {
+ printf("%s: cf_send_cmd(CMD_WRITE_SECTOR) failed: %d\n", __func__, error);
+ return (error);
+ }
if (bus_width == 8) {
volatile uint8_t *task_file;
@@ -324,6 +343,7 @@ static void cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
#ifdef OCTEON_VISUAL_CF_1
octeon_led_write_char(1, ' ');
#endif
+ return (0);
}
@@ -335,10 +355,11 @@ static void cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
* it in the drive_param structure
*
*/
-static void cf_cmd_identify (void)
+static int cf_cmd_identify (void)
{
int count;
uint8_t status;
+ int error;
if (bus_width == 8) {
volatile uint8_t *task_file;
@@ -356,11 +377,11 @@ static void cf_cmd_identify (void)
task_file[TF_DRV_HEAD] = 0;
task_file[TF_COMMAND] = CMD_IDENTIFY;
- cf_wait_busy();
-
- for (count = 0; count < SECTOR_SIZE; count++)
- drive_param.u.buf[count] = task_file[TF_DATA];
-
+ error = cf_wait_busy();
+ if (error == 0) {
+ for (count = 0; count < SECTOR_SIZE; count++)
+ drive_param.u.buf[count] = task_file[TF_DATA];
+ }
} else {
volatile uint16_t *task_file;
@@ -374,17 +395,22 @@ static void cf_cmd_identify (void)
task_file[TF_CYL_LSB/2] = 0; /* this includes TF_CYL_MSB */
task_file[TF_DRV_HEAD/2] = 0 | (CMD_IDENTIFY<<8); /* this includes TF_COMMAND */
- cf_wait_busy();
-
- for (count = 0; count < SECTOR_SIZE; count+=2) {
- uint16_t temp;
- temp = task_file[TF_DATA];
-
- /* endianess will be swapped below */
- drive_param.u.buf[count] = (temp & 0xff);
- drive_param.u.buf[count+1] = (temp & 0xff00)>>8;
+ error = cf_wait_busy();
+ if (error == 0) {
+ for (count = 0; count < SECTOR_SIZE; count+=2) {
+ uint16_t temp;
+ temp = task_file[TF_DATA];
+
+ /* endianess will be swapped below */
+ drive_param.u.buf[count] = (temp & 0xff);
+ drive_param.u.buf[count+1] = (temp & 0xff00)>>8;
+ }
}
}
+ if (error != 0) {
+ printf("%s: identify failed: %d\n", __func__, error);
+ return (error);
+ }
cf_swap_ascii(drive_param.u.driveid.model, drive_param.model);
@@ -394,6 +420,7 @@ static void cf_cmd_identify (void)
drive_param.sec_track = SWAP_SHORT (drive_param.u.driveid.cur_sectors);
drive_param.nr_sectors = SWAP_LONG (drive_param.u.driveid.lba_capacity);
+ return (0);
}
@@ -404,7 +431,7 @@ static void cf_cmd_identify (void)
* Send command to read/write one sector specified by lba.
*
*/
-static void cf_send_cmd (uint32_t lba, uint8_t cmd)
+static int cf_send_cmd (uint32_t lba, uint8_t cmd)
{
uint8_t status;
@@ -439,7 +466,7 @@ static void cf_send_cmd (uint32_t lba, uint8_t cmd)
}
- cf_wait_busy();
+ return (cf_wait_busy());
}
/* ------------------------------------------------------------------- *
@@ -448,12 +475,16 @@ static void cf_send_cmd (uint32_t lba, uint8_t cmd)
*
* Wait until the drive finishes a given command and data is
* ready to be transferred. This is done by repeatedly checking
- * the BSY and DRQ bits of the status register. When the controller
- * is ready for data transfer, it clears the BSY bit and sets the
- * DRQ bit.
+ * the BSY bit of the status register. When the controller is ready for
+ * data transfer, it clears the BSY bit and sets the DRQ bit.
+ *
+ * If the DF bit is ever set, we return error.
*
+ * This code originally spun on DRQ. If that behavior turns out to be
+ * necessary, a flag can be added or this function can be called
+ * repeatedly as long as it is returning ENXIO.
*/
-static void cf_wait_busy (void)
+static int cf_wait_busy (void)
{
uint8_t status;
@@ -469,7 +500,11 @@ static void cf_wait_busy (void)
task_file = (volatile uint8_t *)base_addr;
status = task_file[TF_STATUS];
- while ((status & STATUS_BSY) == STATUS_BSY || (status & STATUS_DRQ) != STATUS_DRQ ) {
+ while ((status & STATUS_BSY) == STATUS_BSY) {
+ if ((status & STATUS_DF) != 0) {
+ printf("%s: device fault (status=%x)\n", __func__, status);
+ return (EIO);
+ }
DELAY(WAIT_DELAY);
status = task_file[TF_STATUS];
}
@@ -478,15 +513,24 @@ static void cf_wait_busy (void)
task_file = (volatile uint16_t *)base_addr;
status = task_file[TF_STATUS/2]>>8;
- while ((status & STATUS_BSY) == STATUS_BSY || (status & STATUS_DRQ) != STATUS_DRQ ) {
+ while ((status & STATUS_BSY) == STATUS_BSY) {
+ if ((status & STATUS_DF) != 0) {
+ printf("%s: device fault (status=%x)\n", __func__, status);
+ return (EIO);
+ }
DELAY(WAIT_DELAY);
status = (uint8_t)(task_file[TF_STATUS/2]>>8);
}
}
+ if ((status & STATUS_DRQ) == 0) {
+ printf("%s: device not ready (status=%x)\n", __func__, status);
+ return (ENXIO);
+ }
#ifdef OCTEON_VISUAL_CF_2
octeon_led_write_char(2, ' ');
#endif
+ return (0);
}
/* ------------------------------------------------------------------- *
@@ -522,9 +566,7 @@ static int cf_probe (device_t dev)
device_set_desc(dev, "Octeon Compact Flash Driver");
- cf_cmd_identify();
-
- return (0);
+ return (cf_cmd_identify());
}
/* ------------------------------------------------------------------- *
@@ -543,7 +585,6 @@ static void cf_identify (driver_t *drv, device_t parent)
int count = 0;
octeon_mio_boot_reg_cfgx_t cfg;
-
if (!octeon_board_real())
return;
diff --git a/sys/mips/cavium/octeon_machdep.c b/sys/mips/cavium/octeon_machdep.c
index e3f2fbd..f55c7ea 100644
--- a/sys/mips/cavium/octeon_machdep.c
+++ b/sys/mips/cavium/octeon_machdep.c
@@ -730,8 +730,6 @@ platform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
{
uint64_t platform_counter_freq;
- boothowto |= RB_SINGLE;
-
/* Initialize pcpu stuff */
mips_pcpu0_init();
mips_timer_early_init(OCTEON_CLOCK_DEFAULT);
@@ -873,8 +871,9 @@ int octeon_chip_rev_major = 0, octeon_chip_rev_minor = 0, octeon_chip_type = 0;
static octeon_boot_descriptor_t *app_desc_ptr;
static cvmx_bootinfo_t *cvmx_desc_ptr;
-#define OCTEON_BOARD_TYPE_NONE 0
-#define OCTEON_BOARD_TYPE_SIM 1
+#define OCTEON_BOARD_TYPE_NONE 0
+#define OCTEON_BOARD_TYPE_SIM 1
+#define OCTEON_BOARD_TYPE_CN3010_EVB_HS5 11
#define OCTEON_CLOCK_MIN (100 * 1000 * 1000)
#define OCTEON_CLOCK_MAX (800 * 1000 * 1000)
@@ -886,11 +885,23 @@ static cvmx_bootinfo_t *cvmx_desc_ptr;
int
octeon_board_real(void)
{
- if ((octeon_board_type == OCTEON_BOARD_TYPE_NONE) ||
- (octeon_board_type == OCTEON_BOARD_TYPE_SIM) ||
- !octeon_board_rev_major)
+ switch (octeon_board_type) {
+ case OCTEON_BOARD_TYPE_NONE:
+ case OCTEON_BOARD_TYPE_SIM:
return 0;
- return 1;
+ case OCTEON_BOARD_TYPE_CN3010_EVB_HS5:
+ /*
+ * XXX
+ * The CAM-0100 identifies itself as type 11, revision 0.0,
+ * despite its being rather real. Disable the revision check
+ * for type 11.
+ */
+ return 1;
+ default:
+ if (octeon_board_rev_major == 0)
+ return 0;
+ return 1;
+ }
}
static void
diff --git a/sys/mips/cavium/octeon_pcmap_regs.h b/sys/mips/cavium/octeon_pcmap_regs.h
index a80c3d4..16dff5b 100644
--- a/sys/mips/cavium/octeon_pcmap_regs.h
+++ b/sys/mips/cavium/octeon_pcmap_regs.h
@@ -90,350 +90,228 @@ extern struct pcpu *cpuid_to_pcpu[];
#define OCTEON_SYNCW __asm __volatile (".word 0x10f" : : )
#define OCTEON_SYNCWS __asm __volatile (".word 0x14f" : : )
-#if defined(__mips_n32) || defined(__mips_n64)
+#if defined(__mips_n64)
+#define oct_write64(a, v) (*(volatile uint64_t *)(a) = (uint64_t)(v))
+#define oct_write8_x8(a, v) (*(volatile uint8_t *)(a) = (uint8_t)(v))
-static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
-{
- uint64_t *ptr = (uint64_t *) csr_addr;
- *ptr = val64;
+#define OCT_READ(n, t) \
+static inline t oct_read ## n(uintptr_t a) \
+{ \
+ volatile t *p = (volatile t *)a; \
+ return (*p); \
}
-static inline void oct_write64_int64 (uint64_t csr_addr, int64_t val64i)
-{
- int64_t *ptr = (int64_t *) csr_addr;
- *ptr = val64i;
-}
+OCT_READ(8, uint8_t);
+OCT_READ(16, uint16_t);
+OCT_READ(32, uint32_t);
+OCT_READ(64, uint64_t);
-static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
+#elif defined(__mips_n32) || defined(__mips_o32)
+#if defined(__mips_n32)
+static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
{
- uint64_t *ptr = (uint64_t *) csr_addr;
- *ptr = (uint64_t) val8;
+ __asm __volatile (
+ ".set push\n"
+ ".set mips64\n"
+ "sd %0, 0(%1)\n"
+ ".set pop\n"
+ :
+ : "r"(val64), "r"(csr_addr));
}
-static inline void oct_write8 (uint64_t csr_addr, uint8_t val8)
+static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
{
- oct_write64(csr_addr, (uint64_t) val8);
-}
+ __asm __volatile (
+ ".set push\n"
+ ".set mips64\n"
+ "sb %0, 0(%1)\n"
+ ".set pop\n"
+ :
+ : "r"(val8), "r"(csr_addr));
+}
+
+#define OCT_READ(n, t, insn) \
+static inline t oct_read ## n(uint64_t a) \
+{ \
+ uint64_t tmp; \
+ \
+ __asm __volatile ( \
+ ".set push\n" \
+ ".set mips64\n" \
+ insn "\t%0, 0(%1)\n" \
+ ".set pop\n" \
+ : "=r"(tmp) \
+ : "r"(a)); \
+ return ((t)tmp); \
+}
+
+OCT_READ(8, uint8_t, "lb");
+OCT_READ(16, uint16_t, "lh");
+OCT_READ(32, uint32_t, "lw");
+OCT_READ(64, uint64_t, "ld");
+#else
-static inline void oct_write16 (uint64_t csr_addr, uint16_t val16)
+/*
+ * XXX
+ * Add o32 variants that load the address into a register and the result out
+ * of a register properly, and simply disable interrupts before and after and
+ * hope that we don't need to refill or modify the TLB to access the address.
+ * I'd be a lot happier if csr_addr were a physical address and we mapped it
+ * into XKPHYS here so that we could guarantee that interrupts were the only
+ * kind of exception we needed to worry about.
+ *
+ * Also, some of this inline assembly is needlessly verbose. Oh, well.
+ */
+static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
{
- oct_write64(csr_addr, (uint64_t) val16);
-}
+ uint32_t csr_addrh = csr_addr >> 32;
+ uint32_t csr_addrl = csr_addr;
+ uint32_t valh = val64 >> 32;
+ uint32_t vall = val64;
+ uint32_t tmp1;
+ uint32_t tmp2;
+ uint32_t tmp3;
+ register_t sr;
-static inline void oct_write32 (uint64_t csr_addr, uint32_t val32)
-{
- oct_write64(csr_addr, (uint64_t) val32);
-}
+ sr = intr_disable();
-static inline uint8_t oct_read8 (uint64_t csr_addr)
-{
- uint8_t *ptr = (uint8_t *) csr_addr;
- return (*ptr);
+ __asm __volatile (
+ ".set push\n"
+ ".set mips64\n"
+ ".set noreorder\n"
+ ".set noat\n"
+ "dsll %0, %3, 32\n"
+ "dsll %1, %5, 32\n"
+ "dsll %2, %4, 32\n"
+ "dsrl %2, %2, 32\n"
+ "or %0, %0, %2\n"
+ "dsll %2, %6, 32\n"
+ "dsrl %2, %2, 32\n"
+ "or %1, %1, %2\n"
+ "sd %0, 0(%1)\n"
+ ".set pop\n"
+ : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
+ : "r" (valh), "r" (vall), "r" (csr_addrh), "r" (csr_addrl));
+
+ intr_restore(sr);
}
-static inline uint8_t oct_read16 (uint64_t csr_addr)
+static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
{
- uint16_t *ptr = (uint16_t *) csr_addr;
- return (*ptr);
-}
+ uint32_t csr_addrh = csr_addr >> 32;
+ uint32_t csr_addrl = csr_addr;
+ uint32_t tmp1;
+ uint32_t tmp2;
+ register_t sr;
+ sr = intr_disable();
-static inline uint32_t oct_read32 (uint64_t csr_addr)
-{
- uint32_t *ptr = (uint32_t *) csr_addr;
- return (*ptr);
-}
+ __asm __volatile (
+ ".set push\n"
+ ".set mips64\n"
+ ".set noreorder\n"
+ ".set noat\n"
+ "dsll %0, %3, 32\n"
+ "dsll %1, %4, 32\n"
+ "dsrl %1, %1, 32\n"
+ "or %0, %0, %1\n"
+ "sb %2, 0(%0)\n"
+ ".set pop\n"
+ : "=&r" (tmp1), "=&r" (tmp2)
+ : "r" (val8), "r" (csr_addrh), "r" (csr_addrl));
+
+ intr_restore(sr);
+}
+
+#define OCT_READ(n, t, insn) \
+static inline t oct_read ## n(uint64_t csr_addr) \
+{ \
+ uint32_t csr_addrh = csr_addr >> 32; \
+ uint32_t csr_addrl = csr_addr; \
+ uint32_t tmp1, tmp2; \
+ register_t sr; \
+ \
+ sr = intr_disable(); \
+ \
+ __asm __volatile ( \
+ ".set push\n" \
+ ".set mips64\n" \
+ ".set noreorder\n" \
+ ".set noat\n" \
+ "dsll %1, %2, 32\n" \
+ "dsll %0, %3, 32\n" \
+ "dsrl %0, %0, 32\n" \
+ "or %1, %1, %0\n" \
+ "lb %1, 0(%1)\n" \
+ ".set pop\n" \
+ : "=&r" (tmp1), "=&r" (tmp2) \
+ : "r" (csr_addrh), "r" (csr_addrl)); \
+ \
+ intr_restore(sr); \
+ \
+ return ((t)tmp2); \
+}
+
+OCT_READ(8, uint8_t, "lb");
+OCT_READ(16, uint16_t, "lh");
+OCT_READ(32, uint32_t, "lw");
static inline uint64_t oct_read64 (uint64_t csr_addr)
{
- uint64_t *ptr = (uint64_t *) csr_addr;
- return (*ptr);
-}
-
-static inline int32_t oct_readint32 (uint64_t csr_addr)
-{
- int32_t *ptr = (int32_t *) csr_addr;
- return (*ptr);
-}
-
-
-
-#else
-
-
-/* ABI o32 */
-
-
-/*
- * Read/write functions
- */
-static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
-{
- uint32_t csr_addrh = csr_addr >> 32;
- uint32_t csr_addrl = csr_addr;
- uint32_t valh = (uint64_t)val64 >> 32;
- uint32_t vall = val64;
- uint32_t tmp1;
- uint32_t tmp2;
- uint32_t tmp3;
+ uint32_t csr_addrh = csr_addr >> 32;
+ uint32_t csr_addrl = csr_addr;
+ uint32_t valh;
+ uint32_t vall;
+ register_t sr;
- __asm __volatile (
- ".set mips64\n"
- "dsll %0, %3, 32\n"
- "dsll %1, %5, 32\n"
- "dsll %2, %4, 32\n"
- "dsrl %2, %2, 32\n"
- "or %0, %0, %2\n"
- "dsll %2, %6, 32\n"
- "dsrl %2, %2, 32\n"
- "or %1, %1, %2\n"
- "sd %0, 0(%1)\n"
- ".set mips0\n"
- : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
- : "r" (valh), "r" (vall),
- "r" (csr_addrh), "r" (csr_addrl)
- );
-}
-
-static inline void oct_write64_int64 (uint64_t csr_addr, int64_t val64i)
-{
- uint32_t csr_addrh = csr_addr >> 32;
- uint32_t csr_addrl = csr_addr;
- int32_t valh = (uint64_t)val64i >> 32;
- int32_t vall = val64i;
- uint32_t tmp1;
- uint32_t tmp2;
- uint32_t tmp3;
+ sr = intr_disable();
- __asm __volatile (
+ __asm __volatile (
+ ".set push\n"
".set mips64\n"
- "dsll %0, %3, 32\n"
- "dsll %1, %5, 32\n"
- "dsll %2, %4, 32\n"
- "dsrl %2, %2, 32\n"
- "or %0, %0, %2\n"
- "dsll %2, %6, 32\n"
- "dsrl %2, %2, 32\n"
- "or %1, %1, %2\n"
- "sd %0, 0(%1)\n"
- ".set mips0\n"
- : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
- : "r" (valh), "r" (vall),
- "r" (csr_addrh), "r" (csr_addrl)
- );
+ ".set noreorder\n"
+ ".set noat\n"
+ "dsll %0, %2, 32\n"
+ "dsll %1, %3, 32\n"
+ "dsrl %1, %1, 32\n"
+ "or %0, %0, %1\n"
+ "ld %1, 0(%0)\n"
+ "dsrl %0, %1, 32\n"
+ "dsll %1, %1, 32\n"
+ "dsrl %1, %1, 32\n"
+ ".set pop\n"
+ : "=&r" (valh), "=&r" (vall)
+ : "r" (csr_addrh), "r" (csr_addrl));
+
+ intr_restore(sr);
+
+ return ((uint64_t)valh << 32) | vall;
}
+#endif
+#endif
-/*
- * oct_write8_x8
- *
- * 8 bit data write into IO Space. Written using an 8 bit bus io transaction
- */
-static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
-{
- uint32_t csr_addrh = csr_addr>>32;
- uint32_t csr_addrl = csr_addr;
- uint32_t tmp1;
- uint32_t tmp2;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %0, %3, 32\n"
- "dsll %1, %4, 32\n"
- "dsrl %1, %1, 32\n"
- "or %0, %0, %1\n"
- "sb %2, 0(%0)\n"
- ".set mips0\n"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "r" (val8), "r" (csr_addrh), "r" (csr_addrl) );
-}
+#define oct_write64_int64(a, v) (oct_write64(a, (int64_t)(v)))
/*
- * oct_write8
- *
- * 8 bit data write into IO Space. Written using a 64 bit bus io transaction
+ * Most write bus transactions are actually 64-bit on Octeon.
*/
static inline void oct_write8 (uint64_t csr_addr, uint8_t val8)
{
-#if 1
oct_write64(csr_addr, (uint64_t) val8);
-#else
-
- uint32_t csr_addrh = csr_addr>>32;
- uint32_t csr_addrl = csr_addr;
- uint32_t tmp1;
- uint32_t tmp2;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %0, %3, 32\n"
- "dsll %1, %4, 32\n"
- "dsrl %1, %1, 32\n"
- "or %0, %0, %1\n"
- "sb %2, 0(%0)\n"
- ".set mips0\n"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "r" (val8), "r" (csr_addrh), "r" (csr_addrl) );
-#endif
}
static inline void oct_write16 (uint64_t csr_addr, uint16_t val16)
{
-#if 1
oct_write64(csr_addr, (uint64_t) val16);
-
-#else
- uint32_t csr_addrh = csr_addr>>32;
- uint32_t csr_addrl = csr_addr;
- uint32_t tmp1;
- uint32_t tmp2;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %0, %3, 32\n"
- "dsll %1, %4, 32\n"
- "dsrl %1, %1, 32\n"
- "or %0, %0, %1\n"
- "sh %2, 0(%0)\n"
- ".set mips0\n"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "r" (val16), "r" (csr_addrh), "r" (csr_addrl) );
-#endif
}
static inline void oct_write32 (uint64_t csr_addr, uint32_t val32)
{
-#if 1
oct_write64(csr_addr, (uint64_t) val32);
-#else
-
- uint32_t csr_addrh = csr_addr>>32;
- uint32_t csr_addrl = csr_addr;
- uint32_t tmp1;
- uint32_t tmp2;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %0, %3, 32\n"
- "dsll %1, %4, 32\n"
- "dsrl %1, %1, 32\n"
- "or %0, %0, %1\n"
- "sw %2, 0(%0)\n"
- ".set mips0\n"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "r" (val32), "r" (csr_addrh), "r" (csr_addrl) );
-#endif
-}
-
-
-
-static inline uint8_t oct_read8 (uint64_t csr_addr)
-{
- uint32_t csr_addrh = csr_addr>>32;
- uint32_t csr_addrl = csr_addr;
- uint32_t tmp1, tmp2;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %1, %2, 32\n"
- "dsll %0, %3, 32\n"
- "dsrl %0, %0, 32\n"
- "or %1, %1, %0\n"
- "lb %1, 0(%1)\n"
- ".set mips0\n"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "r" (csr_addrh), "r" (csr_addrl) );
- return ((uint8_t) tmp2);
-}
-
-static inline uint8_t oct_read16 (uint64_t csr_addr)
-{
- uint32_t csr_addrh = csr_addr>>32;
- uint32_t csr_addrl = csr_addr;
- uint32_t tmp1, tmp2;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %1, %2, 32\n"
- "dsll %0, %3, 32\n"
- "dsrl %0, %0, 32\n"
- "or %1, %1, %0\n"
- "lh %1, 0(%1)\n"
- ".set mips0\n"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "r" (csr_addrh), "r" (csr_addrl) );
- return ((uint16_t) tmp2);
-}
-
-
-static inline uint32_t oct_read32 (uint64_t csr_addr)
-{
- uint32_t csr_addrh = csr_addr>>32;
- uint32_t csr_addrl = csr_addr;
- uint32_t val32;
- uint32_t tmp;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %0, %2, 32\n"
- "dsll %1, %3, 32\n"
- "dsrl %1, %1, 32\n"
- "or %0, %0, %1\n"
- "lw %0, 0(%0)\n"
- ".set mips0\n"
- : "=&r" (val32), "=&r" (tmp)
- : "r" (csr_addrh), "r" (csr_addrl) );
- return (val32);
-}
-
-
-static inline uint64_t oct_read64 (uint64_t csr_addr)
-{
- uint32_t csr_addrh = csr_addr >> 32;
- uint32_t csr_addrl = csr_addr;
- uint32_t valh;
- uint32_t vall;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %0, %2, 32\n"
- "dsll %1, %3, 32\n"
- "dsrl %1, %1, 32\n"
- "or %0, %0, %1\n"
- "ld %1, 0(%0)\n"
- "dsrl %0, %1, 32\n"
- "dsll %1, %1, 32\n"
- "dsrl %1, %1, 32\n"
- ".set mips0\n"
- : "=&r" (valh), "=&r" (vall)
- : "r" (csr_addrh), "r" (csr_addrl)
- );
- return ((uint64_t)valh << 32) | vall;
}
-
-static inline int32_t oct_readint32 (uint64_t csr_addr)
-{
- uint32_t csr_addrh = csr_addr>>32;
- uint32_t csr_addrl = csr_addr;
- int32_t val32;
- uint32_t tmp;
-
- __asm __volatile (
- ".set mips64\n"
- "dsll %0, %2, 32\n"
- "dsll %1, %3, 32\n"
- "dsrl %1, %1, 32\n"
- "or %0, %0, %1\n"
- "lw %0, 0(%0)\n"
- : "=&r" (val32), "=&r" (tmp)
- : "r" (csr_addrh), "r" (csr_addrl) );
- return (val32);
-}
-
-
-#endif
-
+#define oct_readint32(a) ((int32_t)oct_read32((a)))
#define OCTEON_HW_BASE ((volatile uint64_t *) 0L)
#define OCTEON_REG_OFFSET (-4 * 1024ll) /* local scratchpad reg base */
@@ -589,7 +467,7 @@ typedef enum {
/* PTR_SIZE == sizeof(uint32_t) */
-#ifdef ISA_MIPS32
+#if defined(__mips_n32) || defined(__mips_o32)
#define mipsx_addr_size uint32_t // u_int64
#define MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT 30 // 62
#define MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED 0x1fffffff // 0x1fffffff
diff --git a/sys/mips/conf/AR71XX b/sys/mips/conf/AR71XX
index 30126bf..4ee6aab 100644
--- a/sys/mips/conf/AR71XX
+++ b/sys/mips/conf/AR71XX
@@ -15,7 +15,7 @@ files "../atheros/files.ar71xx"
hints "AR71XX.hints"
makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
-makeoptions MODULES_OVERRIDE=""
+#makeoptions MODULES_OVERRIDE=""
options DDB
options KDB
@@ -67,10 +67,11 @@ device ath_rate_sample
device mii
device arge
-# device usb
-# options USB_EHCI_BIG_ENDIAN_DESC # handle big-endian byte order
+device usb
+options USB_EHCI_BIG_ENDIAN_DESC # handle big-endian byte order
# options USB_DEBUG
-# device ehci
+device ohci
+device ehci
device spibus
device ar71xx_spi
diff --git a/sys/mips/conf/OCTEON1 b/sys/mips/conf/OCTEON1
index b326823..c8597dc 100644
--- a/sys/mips/conf/OCTEON1
+++ b/sys/mips/conf/OCTEON1
@@ -81,6 +81,8 @@ nodevice uart_ns8250
device rgmii
#options VERBOSE_SYSINIT
+device bpf
+device random
#
# Use the following for Compact Flash file-system
diff --git a/sys/mips/conf/OCTEON1-32 b/sys/mips/conf/OCTEON1-32
index 7962a06..870a141 100644
--- a/sys/mips/conf/OCTEON1-32
+++ b/sys/mips/conf/OCTEON1-32
@@ -70,6 +70,8 @@ nodevice uart_ns8250
device rgmii
#options VERBOSE_SYSINIT
+device bpf
+device random
#
# Use the following for Compact Flash file-system
diff --git a/sys/mips/include/bus.h b/sys/mips/include/bus.h
index ccaeb34..2ab347b 100644
--- a/sys/mips/include/bus.h
+++ b/sys/mips/include/bus.h
@@ -713,6 +713,8 @@ void __bs_c(f,_bs_c_8) (void *t, bus_space_handle_t bsh1, \
#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
#define BUS_SPACE_MAXSIZE 0xFFFFFFFF
+#define BUS_SPACE_UNRESTRICTED (~0)
+
/*
* declare generic bus space, it suits all needs in
*/
diff --git a/sys/mips/include/clock.h b/sys/mips/include/clock.h
index 62b5112..7dbf4ab 100644
--- a/sys/mips/include/clock.h
+++ b/sys/mips/include/clock.h
@@ -34,6 +34,14 @@ void mips_timer_init_params(uint64_t, int);
extern uint64_t counter_freq;
extern int clocks_running;
+/*
+ * The 'platform_timecounter' pointer may be used to register a
+ * platform-specific timecounter.
+ *
+ * A default timecounter based on the CP0 COUNT register is always registered.
+ */
+extern struct timecounter *platform_timecounter;
+
#endif
#endif /* !_MACHINE_CLOCK_H_ */
diff --git a/sys/mips/include/cpu.h b/sys/mips/include/cpu.h
index 5a1cb9d..1ec1cfc 100644
--- a/sys/mips/include/cpu.h
+++ b/sys/mips/include/cpu.h
@@ -50,22 +50,8 @@
#include <machine/psl.h>
#include <machine/endian.h>
-#define MIPS_CACHED_MEMORY_ADDR 0x80000000
-#define MIPS_UNCACHED_MEMORY_ADDR 0xa0000000
-#define MIPS_MAX_MEM_ADDR 0xbe000000
-#define MIPS_RESERVED_ADDR 0xbfc80000
-
#define MIPS_KSEG0_LARGEST_PHYS 0x20000000
-#define MIPS_CACHED_TO_PHYS(x) ((uintptr_t)(x) & 0x1fffffff)
-#define MIPS_PHYS_TO_CACHED(x) ((uintptr_t)(x) | MIPS_CACHED_MEMORY_ADDR)
-#define MIPS_UNCACHED_TO_PHYS(x) ((uintptr_t)(x) & 0x1fffffff)
-#define MIPS_PHYS_TO_UNCACHED(x) ((uintptr_t)(x) | MIPS_UNCACHED_MEMORY_ADDR)
-
#define MIPS_PHYS_MASK (0x1fffffff)
-#define MIPS_PA_2_K1VA(x) (MIPS_KSEG1_START | ((x) & MIPS_PHYS_MASK))
-
-#define MIPS_VA_TO_CINDEX(x) ((uintptr_t)(x) & 0xffffff | MIPS_CACHED_MEMORY_ADDR)
-#define MIPS_CACHED_TO_UNCACHED(x) (MIPS_PHYS_TO_UNCACHED(MIPS_CACHED_TO_PHYS(x)))
#define MIPS_PHYS_TO_KSEG0(x) ((uintptr_t)(x) | MIPS_KSEG0_START)
#define MIPS_PHYS_TO_KSEG1(x) ((uintptr_t)(x) | MIPS_KSEG1_START)
diff --git a/sys/mips/include/cpufunc.h b/sys/mips/include/cpufunc.h
index d4ca0f1..f9100ea 100644
--- a/sys/mips/include/cpufunc.h
+++ b/sys/mips/include/cpufunc.h
@@ -283,6 +283,35 @@ breakpoint(void)
__asm __volatile ("break");
}
+#if defined(__GNUC__) && !defined(__mips_o32)
+static inline uint64_t
+mips3_ld(const volatile uint64_t *va)
+{
+ uint64_t rv;
+
+#if defined(_LP64)
+ rv = *va;
+#else
+ __asm volatile("ld %0,0(%1)" : "=d"(rv) : "r"(va));
+#endif
+
+ return (rv);
+}
+
+static inline void
+mips3_sd(volatile uint64_t *va, uint64_t v)
+{
+#if defined(_LP64)
+ *va = v;
+#else
+ __asm volatile("sd %0,0(%1)" :: "r"(v), "r"(va));
+#endif
+}
+#else
+uint64_t mips3_ld(volatile uint64_t *va);
+void mips3_sd(volatile uint64_t *, uint64_t);
+#endif /* __GNUC__ */
+
#endif /* _KERNEL */
#define readb(va) (*(volatile uint8_t *) (va))
diff --git a/sys/mips/include/cpuregs.h b/sys/mips/include/cpuregs.h
index f1f2485..74e789c 100644
--- a/sys/mips/include/cpuregs.h
+++ b/sys/mips/include/cpuregs.h
@@ -89,12 +89,6 @@
#define MIPS_KSEG2_END MIPS_KSSEG_END
#define MIPS_KSEG3_START 0xe0000000
#define MIPS_KSEG3_END 0xffffffff
-#define MIPS_MAX_MEM_ADDR 0xbe000000
-#define MIPS_RESERVED_ADDR 0xbfc80000
-
-/* Map virtual address to index in mips3 r4k virtually-indexed cache */
-#define MIPS3_VA_TO_CINDEX(x) \
- ((unsigned)(x) & 0xffffff | MIPS_KSEG0_START)
#define MIPS_PHYS_TO_XKPHYS(cca,x) \
((0x2ULL << 62) | ((unsigned long long)(cca) << 59) | (x))
@@ -583,6 +577,8 @@
#define MIPS_CONFIG1_TLBSZ_MASK 0x7E000000 /* bits 30..25 # tlb entries minus one */
#define MIPS_CONFIG1_TLBSZ_SHIFT 25
+#define MIPS_MAX_TLB_ENTRIES 64
+
#define MIPS_CONFIG1_IS_MASK 0x01C00000 /* bits 24..22 icache sets per way */
#define MIPS_CONFIG1_IS_SHIFT 22
#define MIPS_CONFIG1_IL_MASK 0x00380000 /* bits 21..19 icache line size */
diff --git a/sys/mips/include/db_machdep.h b/sys/mips/include/db_machdep.h
index ea97120..d7bf69a 100644
--- a/sys/mips/include/db_machdep.h
+++ b/sys/mips/include/db_machdep.h
@@ -92,7 +92,6 @@ db_addr_t next_instr_address(db_addr_t, boolean_t);
#define DB_SMALL_VALUE_MIN (-0x400001)
int db_inst_type(int);
-void db_dump_tlb(int, int);
db_addr_t branch_taken(int inst, db_addr_t pc);
void stacktrace_subr(register_t pc, register_t sp, register_t ra, int (*)(const char *, ...));
int kdbpeek(int *);
diff --git a/sys/mips/include/kdb.h b/sys/mips/include/kdb.h
index cd8c618..6ca6654 100644
--- a/sys/mips/include/kdb.h
+++ b/sys/mips/include/kdb.h
@@ -32,6 +32,8 @@
#include <machine/frame.h>
+#define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid]
+
static __inline void
kdb_cpu_clear_singlestep(void)
{
diff --git a/sys/mips/include/param.h b/sys/mips/include/param.h
index 8edd48e..9d48702 100644
--- a/sys/mips/include/param.h
+++ b/sys/mips/include/param.h
@@ -128,14 +128,13 @@
#define MAXDUMPPGS 1 /* xxx: why is this only one? */
/*
- * NOTE: In FreeBSD, Uarea's don't have a fixed address.
- * Therefore, any code imported from OpenBSD which depends on
- * UADDR, UVPN and KERNELSTACK requires porting.
- * XXX: 3 stack pages? Not 4 which would be more efficient from a tlb
- * XXX: point of view.
+ * The kernel stack needs to be aligned on a (PAGE_SIZE * 2) boundary.
+ *
+ * Although we allocate 3 pages for the kernel stack we end up using
+ * only the 2 pages that are aligned on a (PAGE_SIZE * 2) boundary.
*/
#define KSTACK_PAGES 3 /* kernel stack*/
-#define KSTACK_GUARD_PAGES 0 /* pages of kstack guard; 0 disables */
+#define KSTACK_GUARD_PAGES 1 /* pages of kstack guard; 0 disables */
#define UPAGES 2
diff --git a/sys/mips/include/pmap.h b/sys/mips/include/pmap.h
index eedd4f3..51ff551 100644
--- a/sys/mips/include/pmap.h
+++ b/sys/mips/include/pmap.h
@@ -219,6 +219,11 @@ pmap_map_fpage(vm_paddr_t pa, struct fpage *fp,
boolean_t check_unmaped);
void pmap_unmap_fpage(vm_paddr_t pa, struct fpage *fp);
+/*
+ * Function to save TLB contents so that they may be inspected in the debugger.
+ */
+extern void pmap_save_tlb(void);
+
#endif /* _KERNEL */
#endif /* !LOCORE */
diff --git a/sys/mips/include/smp.h b/sys/mips/include/smp.h
index 346c863..1cb0596 100644
--- a/sys/mips/include/smp.h
+++ b/sys/mips/include/smp.h
@@ -17,6 +17,8 @@
#ifdef _KERNEL
+#include <machine/pcb.h>
+
/*
* Interprocessor interrupts for SMP.
*/
@@ -31,6 +33,8 @@ void ipi_selected(cpumask_t cpus, int ipi);
void smp_init_secondary(u_int32_t cpuid);
void mpentry(void);
+extern struct pcb stoppcbs[];
+
#endif /* !LOCORE */
#endif /* _KERNEL */
diff --git a/sys/mips/include/trap.h b/sys/mips/include/trap.h
index 1c6be30..f382e70 100644
--- a/sys/mips/include/trap.h
+++ b/sys/mips/include/trap.h
@@ -111,11 +111,10 @@ void trapDump(char *msg);
void MipsFPTrap(u_int, u_int, u_int);
void MipsKernGenException(void);
void MipsKernIntr(void);
-void MipsKernTLBInvalidException(void);
+void MipsTLBInvalidException(void);
void MipsTLBMissException(void);
void MipsUserGenException(void);
void MipsUserIntr(void);
-void MipsUserTLBInvalidException(void);
u_int trap(struct trapframe *);
diff --git a/sys/mips/mips/busdma_machdep.c b/sys/mips/mips/busdma_machdep.c
index f2d41df..a6a7419 100644
--- a/sys/mips/mips/busdma_machdep.c
+++ b/sys/mips/mips/busdma_machdep.c
@@ -687,16 +687,21 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap,
* Count the number of bounce pages
* needed in order to complete this transfer
*/
- vaddr = trunc_page((vm_offset_t)buf);
+ vaddr = (vm_offset_t)buf;
vendaddr = (vm_offset_t)buf + buflen;
while (vaddr < vendaddr) {
+ bus_size_t sg_len;
+
KASSERT(kernel_pmap == pmap, ("pmap is not kernel pmap"));
+ sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK);
paddr = pmap_kextract(vaddr);
if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
- run_filter(dmat, paddr) != 0)
+ run_filter(dmat, paddr) != 0) {
+ sg_len = roundup2(sg_len, dmat->alignment);
map->pagesneeded++;
- vaddr += PAGE_SIZE;
+ }
+ vaddr += sg_len;
}
CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
}
diff --git a/sys/mips/mips/db_trace.c b/sys/mips/mips/db_trace.c
index 4eadc25..9417bcc 100644
--- a/sys/mips/mips/db_trace.c
+++ b/sys/mips/mips/db_trace.c
@@ -162,13 +162,16 @@ loop:
subr = (uintptr_t)MipsUserGenException;
else if (pcBetween(MipsKernIntr, MipsUserIntr))
subr = (uintptr_t)MipsKernIntr;
- else if (pcBetween(MipsUserIntr, MipsKernTLBInvalidException))
+ else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
subr = (uintptr_t)MipsUserIntr;
- else if (pcBetween(MipsKernTLBInvalidException,
- MipsUserTLBInvalidException))
- subr = (uintptr_t)MipsKernTLBInvalidException;
- else if (pcBetween(MipsUserTLBInvalidException, MipsTLBMissException))
- subr = (uintptr_t)MipsUserTLBInvalidException;
+ else if (pcBetween(MipsTLBInvalidException, MipsTLBMissException))
+ subr = (uintptr_t)MipsTLBInvalidException;
+ else if (pcBetween(fork_trampoline, savectx))
+ subr = (uintptr_t)fork_trampoline;
+ else if (pcBetween(savectx, mips_cpu_throw))
+ subr = (uintptr_t)savectx;
+ else if (pcBetween(mips_cpu_throw, cpu_switch))
+ subr = (uintptr_t)cpu_throw;
else if (pcBetween(cpu_switch, MipsSwitchFPState))
subr = (uintptr_t)cpu_switch;
else if (pcBetween(_locore, _locoreEnd)) {
@@ -412,10 +415,8 @@ db_trace_thread(struct thread *thr, int count)
: "=r" (pc)
: "r" (ra));
- }
-
- else {
- ctx = thr->td_pcb;
+ } else {
+ ctx = kdb_thr_ctx(thr);
sp = (register_t)ctx->pcb_context[PREG_SP];
pc = (register_t)ctx->pcb_context[PREG_PC];
ra = (register_t)ctx->pcb_context[PREG_RA];
diff --git a/sys/mips/mips/exception.S b/sys/mips/mips/exception.S
index 02edcde..161e947 100644
--- a/sys/mips/mips/exception.S
+++ b/sys/mips/mips/exception.S
@@ -264,13 +264,13 @@ SlowFault:
mfc0 a0, COP_0_STATUS_REG ;\
li a2, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX) ; \
or a0, a0, a2 ; \
- li a2, ~(MIPS_SR_INT_IE|MIPS_SR_EXL) ; \
+ li a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER) ; \
and a0, a0, a2 ; \
mtc0 a0, COP_0_STATUS_REG
#else
#define CLEAR_STATUS \
mfc0 a0, COP_0_STATUS_REG ;\
- li a2, ~(MIPS_SR_INT_IE|MIPS_SR_EXL) ; \
+ li a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER) ; \
and a0, a0, a2 ; \
mtc0 a0, COP_0_STATUS_REG
#endif
@@ -827,177 +827,168 @@ NNON_LEAF(MipsUserIntr, STAND_FRAME_SIZE, ra)
.set at
END(MipsUserIntr)
-NLEAF(MipsKernTLBInvalidException)
- .set noat
- mfc0 k0, COP_0_BAD_VADDR # get the fault address
-
+NLEAF(MipsTLBInvalidException)
+ .set push
+ .set noat
+ .set noreorder
+ mfc0 k0, COP_0_BAD_VADDR
li k1, VM_MAXUSER_ADDRESS
sltu k1, k0, k1
- beqz k1, 1f
- nop
- GET_CPU_PCPU(k1)
- lw k1, PC_SEGBASE(k1) # works for single cpu????
- beqz k1, _C_LABEL(MipsKernGenException) # seg tab is null
+ bnez k1, 1f
nop
+
+ /* badvaddr = kernel address */
+ lui k1, %hi(_C_LABEL(kernel_segmap))
b 2f
- nop
+ lw k1, %lo(_C_LABEL(kernel_segmap))(k1)
+
1:
- li k1, (VM_MAX_KERNEL_ADDRESS)
- bgez k0, _C_LABEL(MipsKernGenException) # full trap processing
- sltu k1, k1, k0 # check fault address against
- bnez k1, _C_LABEL(MipsKernGenException) # kernel_segmap upper bound
- lui k1, %hi(_C_LABEL(kernel_segmap)) # k1=hi of segbase
- lw k1, %lo(_C_LABEL(kernel_segmap))(k1) # k1=segment tab base
- beqz k1, _C_LABEL(MipsKernGenException) # seg tab is null
+ /* badvaddr = user address */
+ GET_CPU_PCPU(k1)
+ lw k1, PC_SEGBASE(k1)
+
2:
- srl k0, 20 # k0=seg offset (almost)
- andi k0, k0, 0xffc # k0=seg offset (mask 0x3)
-#xxx mips64 unsafe?
- addu k1, k0, k1 # k1=seg entry address
- lw k1, 0(k1) # k1=seg entry
- mfc0 k0, COP_0_BAD_VADDR # k0=bad address (again)
- beq k1, zero, _C_LABEL(MipsKernGenException) # ==0 -- no page table
- srl k0, k0, PGSHIFT-2
- andi k0, k0, 0xffc # compute offset from index
- tlbp # Probe the invalid entry
-#xxx mips64 unsafe?
+ beqz k1, 3f /* invalid page directory pointer */
+ nop
+
+ srl k0, SEGSHIFT - 2
+ andi k0, 0xffc
addu k1, k1, k0
- and k0, k0, 4 # check even/odd page
- nop # required for QED 5230
- bne k0, zero, KernTLBIOdd
+ lw k1, 0(k1)
+ beqz k1, 3f /* invalid page table page pointer */
nop
- mfc0 k0, COP_0_TLB_INDEX
+ mfc0 k0, COP_0_BAD_VADDR
+ srl k0, PGSHIFT - 2
+ andi k0, 0xffc
+ addu k1, k1, k0
+
+ lw k0, 0(k1)
+ andi k0, PTE_V
+ beqz k0, 3f /* invalid page table entry */
nop
- bltz k0, sys_stk_chk
- sltiu k0, k0, VMWIRED_ENTRIES # index below wired entries?
- bne k0, zero, sys_stk_chk
- lw k0, 0(k1) # get PTE entry
+ andi k0, k1, 4
+ bnez k0, odd_page
+ nop
- _SLL k0, k0, WIRED_SHIFT # get rid of "wired" bit
+even_page:
+ lw k0, 0(k1)
+ _SLL k0, k0, WIRED_SHIFT
_SRL k0, k0, WIRED_SHIFT
- _MTC0 k0, COP_0_TLB_LO0 # load PTE entry
- and k0, k0, PTE_V # check for valid entry
- nop # required for QED5230
- beq k0, zero, _C_LABEL(MipsKernGenException) # PTE invalid
- lw k0, 4(k1) # get odd PTE entry
+ _MTC0 k0, COP_0_TLB_LO0
+
+ lw k0, 4(k1)
_SLL k0, k0, WIRED_SHIFT
_SRL k0, k0, WIRED_SHIFT
- _MTC0 k0, COP_0_TLB_LO1 # load PTE entry
- HAZARD_DELAY
- tlbwi # write TLB
- HAZARD_DELAY
- eret
+ _MTC0 k0, COP_0_TLB_LO1
-KernTLBIOdd:
- mfc0 k0, COP_0_TLB_INDEX
+ b tlb_insert_entry
nop
- bltz k0, sys_stk_chk
- sltiu k0, k0, VMWIRED_ENTRIES # index below wired entries?
- bne k0, zero, sys_stk_chk
- lw k0, 0(k1) # get PTE entry
-
- _SLL k0, k0, WIRED_SHIFT # get rid of wired bit
+odd_page:
+ lw k0, 0(k1)
+ _SLL k0, k0, WIRED_SHIFT
_SRL k0, k0, WIRED_SHIFT
- _MTC0 k0, COP_0_TLB_LO1 # save PTE entry
- and k0, k0, PTE_V # check for valid entry
- nop # required for QED5230
- beq k0, zero, _C_LABEL(MipsKernGenException) # PTE invalid
- lw k0, -4(k1) # get even PTE entry
+ _MTC0 k0, COP_0_TLB_LO1
+
+ lw k0, -4(k1)
_SLL k0, k0, WIRED_SHIFT
_SRL k0, k0, WIRED_SHIFT
- _MTC0 k0, COP_0_TLB_LO0 # save PTE entry
+ _MTC0 k0, COP_0_TLB_LO0
+
+tlb_insert_entry:
+ tlbp
HAZARD_DELAY
- tlbwi # update TLB
+ mfc0 k0, COP_0_TLB_INDEX
HAZARD_DELAY
+ bltz k0, tlb_insert_random
+ nop
+ tlbwi
eret
+ ssnop
- .set at
-END(MipsKernTLBInvalidException)
-
-
-NLEAF(MipsUserTLBInvalidException)
- .set noat
- mfc0 k0, COP_0_BAD_VADDR # get the fault address
+tlb_insert_random:
+ tlbwr
+ eret
+ ssnop
- li k1, VM_MAXUSER_ADDRESS
- sltu k1, k0, k1
- beqz k1, _C_LABEL(MipsUserGenException)
+3:
+ /*
+ * Branch to the comprehensive exception processing.
+ */
+ mfc0 k1, COP_0_STATUS_REG
+ andi k1, k1, SR_KSU_USER
+ bnez k1, _C_LABEL(MipsUserGenException)
nop
+
+ /*
+ * Check for kernel stack overflow.
+ */
GET_CPU_PCPU(k1)
- lw k1, PC_SEGBASE(k1) # works for single cpu????
- beqz k1, _C_LABEL(MipsUserGenException) # seg tab is null
- nop
-2:
- srl k0, 20 # k0=seg offset (almost)
- andi k0, k0, 0xffc # k0=seg offset (mask 0x3)
-#xxx mips64 unsafe?
- addu k1, k0, k1 # k1=seg entry address
- lw k1, 0(k1) # k1=seg entry
- mfc0 k0, COP_0_BAD_VADDR # k0=bad address (again)
- beq k1, zero, _C_LABEL(MipsUserGenException) # ==0 -- no page table
- srl k0, k0, PGSHIFT-2
- andi k0, k0, 0xffc # compute offset from index
- tlbp # Probe the invalid entry
-#xxx mips64 unsafe?
- addu k1, k1, k0
- and k0, k0, 4 # check even/odd page
- nop # required for QED 5230
- bne k0, zero, UserTLBIOdd
+ lw k0, PC_CURTHREAD(k1)
+ lw k0, TD_REALKSTACK(k0)
+ sltu k0, k0, sp
+ bnez k0, _C_LABEL(MipsKernGenException)
nop
- mfc0 k0, COP_0_TLB_INDEX
- nop
- bltz k0, _C_LABEL(MipsUserGenException)
+ /*
+ * Kernel stack overflow.
+ *
+ * Move to a valid stack before we call panic. We use the boot stack
+ * for this purpose.
+ */
+ GET_CPU_PCPU(k1)
+ lw k1, PC_CPUID(k1)
+ sll k1, k1, PAGE_SHIFT + 1
- sltiu k0, k0, VMWIRED_ENTRIES # index below wired entries?
- bne k0, zero, _C_LABEL(MipsUserGenException)
- lw k0, 0(k1) # get PTE entry
+ PTR_LA k0, _C_LABEL(pcpu_space)
+ addiu k0, (NBPG * 2)
+ addu k0, k0, k1
- _SLL k0, k0, WIRED_SHIFT # get rid of "wired" bit
- _SRL k0, k0, WIRED_SHIFT
- _MTC0 k0, COP_0_TLB_LO0 # load PTE entry
- and k0, k0, PTE_V # check for valid entry
- nop # required for QED5230
- beq k0, zero, _C_LABEL(MipsUserGenException) # PTE invalid
- lw k0, 4(k1) # get odd PTE entry
- _SLL k0, k0, WIRED_SHIFT
- _SRL k0, k0, WIRED_SHIFT
- _MTC0 k0, COP_0_TLB_LO1 # load PTE entry
- HAZARD_DELAY
- tlbwi # write TLB
- HAZARD_DELAY
- eret
+ /*
+ * Stash the original value of 'sp' so we can update trapframe later.
+ * We assume that SAVE_CPU does not trash 'k1'.
+ */
+ move k1, sp
-UserTLBIOdd:
- mfc0 k0, COP_0_TLB_INDEX
- nop
- bltz k0, _C_LABEL(MipsUserGenException)
- sltiu k0, k0, VMWIRED_ENTRIES # index below wired entries?
+ move sp, k0
+ subu sp, sp, KERN_EXC_FRAME_SIZE
- bne k0, zero, _C_LABEL(MipsUserGenException)
- lw k0, 0(k1) # get PTE entry
+ move k0, ra
+ move ra, zero
+ sw ra, CALLFRAME_RA(sp) /* stop the ddb backtrace right here */
+ sw zero, CALLFRAME_SP(sp)
+ move ra, k0
- _SLL k0, k0, WIRED_SHIFT # get rid of wired bit
- _SRL k0, k0, WIRED_SHIFT
- _MTC0 k0, COP_0_TLB_LO1 # save PTE entry
- and k0, k0, PTE_V # check for valid entry
- nop # required for QED5230
- beq k0, zero, _C_LABEL(MipsUserGenException) # PTE invalid
- lw k0, -4(k1) # get even PTE entry
- _SLL k0, k0, WIRED_SHIFT
- _SRL k0, k0, WIRED_SHIFT
- _MTC0 k0, COP_0_TLB_LO0 # save PTE entry
- HAZARD_DELAY
- tlbwi # update TLB
- HAZARD_DELAY
- eret
+ SAVE_CPU
- .set at
-END(MipsUserTLBInvalidException)
+ /*
+ * Now restore the value of 'sp' at the time of the tlb exception in
+ * the trapframe.
+ */
+ SAVE_REG(k1, SP, sp)
+
+ /*
+ * Squelch any more overflow checks by setting the stack base to 0.
+ */
+ GET_CPU_PCPU(k1)
+ lw k0, PC_CURTHREAD(k1)
+ sw zero, TD_REALKSTACK(k0)
+
+ move a1, a0
+ PANIC("kernel stack overflow - trapframe at %p")
+
+ /*
+ * This nop is necessary so that the 'ra' remains within the bounds
+ * of this handler. Otherwise the ddb backtrace code will think that
+ * the panic() was called from MipsTLBMissException.
+ */
+ nop
+
+ .set pop
+END(MipsTLBInvalidException)
/*----------------------------------------------------------------------------
*
@@ -1048,68 +1039,6 @@ NLEAF(MipsTLBMissException)
tlbwr # write to tlb
HAZARD_DELAY
eret # return from exception
-
-sys_stk_chk:
- GET_CPU_PCPU(k0)
- lw k0, PC_CURTHREAD(k0)
- lw k0, TD_REALKSTACK(k0)
- sltu k0, sp, k0 # check for stack overflow
- beqz k0, _C_LABEL(MipsKernGenException) # not stack overflow
- nop
-
-# stack overflow
- PTR_LA a0, _C_LABEL(_start) - CALLFRAME_SIZ - 8 # set sp to a valid place
- sw sp, 24(a0)
- move sp, a0
- PTR_LA a0, 1f
- mfc0 a2, COP_0_STATUS_REG
- mfc0 a3, COP_0_CAUSE_REG
- _MFC0 a1, COP_0_EXC_PC
- sw a2, 16(sp)
- sw a3, 20(sp)
- move a2, ra
- PTR_LA k0, _C_LABEL(printf)
- jalr k0
- mfc0 a3, COP_0_BAD_VADDR
-
- PTR_LA sp, _C_LABEL(_start) - CALLFRAME_SIZ # set sp to a valid place
-
-#if !defined(SMP) && defined(DDB)
- PTR_LA a0, 2f
- PTR_LA k0, _C_LABEL(trapDump)
- jalr k0
- nop
-
- li a0, 0
- lw a1, _C_LABEL(num_tlbentries)
- PTR_LA k0, _C_LABEL(db_dump_tlb)
- jalr k0
- addu a1, -1
-
-3:
- b 3b
- nop
-#endif
-
- PANIC("kernel stack overflow")
-
- .data
- .globl lastktlbmiss
-lastktlbmiss:
- .word 0
-lastktlbmisspc:
- .word 0
-lastutlbmiss:
- .word 0
-lastutlbmisspc:
- .word 0
-
-1:
- .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n"
-2:
- .asciiz "stack ovf"
- .text
-
.set at
END(MipsTLBMissException)
@@ -1253,7 +1182,7 @@ VECTOR(MipsCache, unknown)
PTR_LA k0, _C_LABEL(MipsCacheException)
li k1, MIPS_PHYS_MASK
and k0, k1
- li k1, MIPS_UNCACHED_MEMORY_ADDR
+ li k1, MIPS_KSEG1_START
or k0, k1
j k0
nop
diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c
index d8520cc..f65db9b 100644
--- a/sys/mips/mips/mp_machdep.c
+++ b/sys/mips/mips/mp_machdep.c
@@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$");
#include <machine/intr_machdep.h>
#include <machine/cache.h>
+struct pcb stoppcbs[MAXCPU];
+
static void *dpcpu;
static struct mtx ap_boot_mtx;
@@ -88,10 +90,14 @@ ipi_selected(cpumask_t cpus, int ipi)
static int
mips_ipi_handler(void *arg)
{
+ int cpu;
cpumask_t cpumask;
u_int ipi, ipi_bitmap;
int bit;
+ cpu = PCPU_GET(cpuid);
+ cpumask = PCPU_GET(cpumask);
+
platform_ipi_clear(); /* quiesce the pending ipi interrupt */
ipi_bitmap = atomic_readandclear_int(PCPU_PTR(pending_ipis));
@@ -120,10 +126,17 @@ mips_ipi_handler(void *arg)
* necessary to add it in the switch.
*/
CTR0(KTR_SMP, "IPI_STOP or IPI_STOP_HARD");
- cpumask = PCPU_GET(cpumask);
+
+ savectx(&stoppcbs[cpu]);
+ pmap_save_tlb();
+
+ /* Indicate we are stopped */
atomic_set_int(&stopped_cpus, cpumask);
+
+ /* Wait for restart */
while ((started_cpus & cpumask) == 0)
cpu_spinwait();
+
atomic_clear_int(&started_cpus, cpumask);
atomic_clear_int(&stopped_cpus, cpumask);
CTR0(KTR_SMP, "IPI_STOP (restart)");
diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c
index 7d3f190..6600980 100644
--- a/sys/mips/mips/nexus.c
+++ b/sys/mips/mips/nexus.c
@@ -73,7 +73,6 @@ struct nexus_device {
#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev))
#define NUM_MIPS_IRQS 6
-#define MIPS_MEM_RID 0x20
static struct rman irq_rman;
static struct rman mem_rman;
diff --git a/sys/mips/mips/pm_machdep.c b/sys/mips/mips/pm_machdep.c
index 712763b..03867b0 100644
--- a/sys/mips/mips/pm_machdep.c
+++ b/sys/mips/mips/pm_machdep.c
@@ -472,7 +472,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
* code by the MIPS elf abi).
*/
void
-exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
{
bzero((caddr_t)td->td_frame, sizeof(struct trapframe));
@@ -481,8 +481,8 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
* Make sp 64-bit aligned.
*/
td->td_frame->sp = ((register_t) stack) & ~(sizeof(__int64_t) - 1);
- td->td_frame->pc = entry & ~3;
- td->td_frame->t9 = entry & ~3; /* abicall req */
+ td->td_frame->pc = imgp->entry_addr & ~3;
+ td->td_frame->t9 = imgp->entry_addr & ~3; /* abicall req */
#if 0
// td->td_frame->sr = SR_KSU_USER | SR_EXL | SR_INT_ENAB;
//? td->td_frame->sr |= idle_mask & ALL_INT_MASK;
@@ -511,7 +511,7 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
td->td_frame->a0 = (register_t) stack;
td->td_frame->a1 = 0;
td->td_frame->a2 = 0;
- td->td_frame->a3 = (register_t)ps_strings;
+ td->td_frame->a3 = (register_t)imgp->ps_strings;
td->td_md.md_flags &= ~MDTD_FPUSED;
if (PCPU_GET(fpcurthread) == td)
diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c
index 4a267dc..73f57e4 100644
--- a/sys/mips/mips/pmap.c
+++ b/sys/mips/mips/pmap.c
@@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
#include <sys/msgbuf.h>
#include <sys/vmmeter.h>
#include <sys/mman.h>
+#include <sys/smp.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -149,6 +150,8 @@ unsigned pmap_max_asid; /* max ASID supported by the system */
vm_offset_t kernel_vm_end;
+static struct tlb tlbstash[MAXCPU][MIPS_MAX_TLB_ENTRIES];
+
static void pmap_asid_alloc(pmap_t pmap);
/*
@@ -205,7 +208,7 @@ struct local_sysmaps {
/* This structure is for large memory
* above 512Meg. We can't (in 32 bit mode)
- * just use the direct mapped MIPS_CACHED_TO_PHYS()
+ * just use the direct mapped MIPS_KSEG0_TO_PHYS()
* macros since we can't see the memory and must
* map it in when we need to access it. In 64
* bit mode this goes away.
@@ -271,7 +274,7 @@ pmap_steal_memory(vm_size_t size)
if (pa >= MIPS_KSEG0_LARGEST_PHYS) {
panic("Out of memory below 512Meg?");
}
- va = MIPS_PHYS_TO_CACHED(pa);
+ va = MIPS_PHYS_TO_KSEG0(pa);
bzero((caddr_t)va, size);
return va;
}
@@ -946,10 +949,21 @@ pmap_unmap_fpage(vm_paddr_t pa, struct fpage *fp)
static int
_pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m)
{
+ vm_offset_t pteva;
/*
* unmap the page table page
*/
+ pteva = (vm_offset_t)pmap->pm_segtab[m->pindex];
+ if (pteva >= VM_MIN_KERNEL_ADDRESS) {
+ pmap_kremove(pteva);
+ kmem_free(kernel_map, pteva, PAGE_SIZE);
+ } else {
+ KASSERT(MIPS_IS_KSEG0_ADDR(pteva),
+ ("_pmap_unwire_pte_hold: 0x%0lx is not in kseg0",
+ (long)pteva));
+ }
+
pmap->pm_segtab[m->pindex] = 0;
--pmap->pm_stats.resident_count;
@@ -994,7 +1008,7 @@ pmap_unuse_pt(pmap_t pmap, vm_offset_t va, vm_page_t mpte)
mpte = pmap->pm_ptphint;
} else {
pteva = *pmap_pde(pmap, va);
- mpte = PHYS_TO_VM_PAGE(MIPS_CACHED_TO_PHYS(pteva));
+ mpte = PHYS_TO_VM_PAGE(vtophys(pteva));
pmap->pm_ptphint = mpte;
}
}
@@ -1026,6 +1040,8 @@ pmap_pinit0(pmap_t pmap)
int
pmap_pinit(pmap_t pmap)
{
+ vm_offset_t ptdva;
+ vm_paddr_t ptdpa;
vm_page_t ptdpg;
int i;
int req;
@@ -1047,8 +1063,17 @@ pmap_pinit(pmap_t pmap)
ptdpg->valid = VM_PAGE_BITS_ALL;
- pmap->pm_segtab = (pd_entry_t *)
- MIPS_PHYS_TO_CACHED(VM_PAGE_TO_PHYS(ptdpg));
+ ptdpa = VM_PAGE_TO_PHYS(ptdpg);
+ if (ptdpa < MIPS_KSEG0_LARGEST_PHYS) {
+ ptdva = MIPS_PHYS_TO_KSEG0(ptdpa);
+ } else {
+ ptdva = kmem_alloc_nofault(kernel_map, PAGE_SIZE);
+ if (ptdva == 0)
+ panic("pmap_pinit: unable to allocate kva");
+ pmap_kenter(ptdva, ptdpa);
+ }
+
+ pmap->pm_segtab = (pd_entry_t *)ptdva;
if ((ptdpg->flags & PG_ZERO) == 0)
bzero(pmap->pm_segtab, PAGE_SIZE);
@@ -1115,7 +1140,15 @@ _pmap_allocpte(pmap_t pmap, unsigned ptepindex, int flags)
pmap->pm_stats.resident_count++;
ptepa = VM_PAGE_TO_PHYS(m);
- pteva = MIPS_PHYS_TO_CACHED(ptepa);
+ if (ptepa < MIPS_KSEG0_LARGEST_PHYS) {
+ pteva = MIPS_PHYS_TO_KSEG0(ptepa);
+ } else {
+ pteva = kmem_alloc_nofault(kernel_map, PAGE_SIZE);
+ if (pteva == 0)
+ panic("_pmap_allocpte: unable to allocate kva");
+ pmap_kenter(pteva, ptepa);
+ }
+
pmap->pm_segtab[ptepindex] = (pd_entry_t)pteva;
/*
@@ -1169,7 +1202,7 @@ retry:
(pmap->pm_ptphint->pindex == ptepindex)) {
m = pmap->pm_ptphint;
} else {
- m = PHYS_TO_VM_PAGE(MIPS_CACHED_TO_PHYS(pteva));
+ m = PHYS_TO_VM_PAGE(vtophys(pteva));
pmap->pm_ptphint = m;
}
m->wire_count++;
@@ -1209,13 +1242,24 @@ retry:
void
pmap_release(pmap_t pmap)
{
+ vm_offset_t ptdva;
vm_page_t ptdpg;
KASSERT(pmap->pm_stats.resident_count == 0,
("pmap_release: pmap resident count %ld != 0",
pmap->pm_stats.resident_count));
- ptdpg = PHYS_TO_VM_PAGE(MIPS_CACHED_TO_PHYS(pmap->pm_segtab));
+ ptdva = (vm_offset_t)pmap->pm_segtab;
+ ptdpg = PHYS_TO_VM_PAGE(vtophys(ptdva));
+
+ if (ptdva >= VM_MIN_KERNEL_ADDRESS) {
+ pmap_kremove(ptdva);
+ kmem_free(kernel_map, ptdva, PAGE_SIZE);
+ } else {
+ KASSERT(MIPS_IS_KSEG0_ADDR(ptdva),
+ ("pmap_release: 0x%0lx is not in kseg0", (long)ptdva));
+ }
+
ptdpg->wire_count--;
atomic_subtract_int(&cnt.v_wire_count, 1);
vm_page_free_zero(ptdpg);
@@ -1285,7 +1329,7 @@ pmap_growkernel(vm_offset_t addr)
*/
panic("Gak, can't handle a k-page table outside of lower 512Meg");
}
- pte = (pt_entry_t *)MIPS_PHYS_TO_CACHED(ptppaddr);
+ pte = (pt_entry_t *)MIPS_PHYS_TO_KSEG0(ptppaddr);
segtab_pde(kernel_segmap, kernel_vm_end) = (pd_entry_t)pte;
/*
@@ -2027,7 +2071,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
(pmap->pm_ptphint->pindex == ptepindex)) {
mpte = pmap->pm_ptphint;
} else {
- mpte = PHYS_TO_VM_PAGE(MIPS_CACHED_TO_PHYS(pteva));
+ mpte = PHYS_TO_VM_PAGE(vtophys(pteva));
pmap->pm_ptphint = mpte;
}
mpte->wire_count++;
@@ -2117,7 +2161,7 @@ pmap_kenter_temporary(vm_paddr_t pa, int i)
} else
#endif
if (pa < MIPS_KSEG0_LARGEST_PHYS) {
- va = MIPS_PHYS_TO_CACHED(pa);
+ va = MIPS_PHYS_TO_KSEG0(pa);
} else {
int cpu;
struct local_sysmaps *sysm;
@@ -2289,7 +2333,7 @@ pmap_zero_page(vm_page_t m)
#endif
if (phys < MIPS_KSEG0_LARGEST_PHYS) {
- va = MIPS_PHYS_TO_CACHED(phys);
+ va = MIPS_PHYS_TO_KSEG0(phys);
bzero((caddr_t)va, PAGE_SIZE);
mips_dcache_wbinv_range(va, PAGE_SIZE);
@@ -2347,7 +2391,7 @@ pmap_zero_page_area(vm_page_t m, int off, int size)
} else
#endif
if (phys < MIPS_KSEG0_LARGEST_PHYS) {
- va = MIPS_PHYS_TO_CACHED(phys);
+ va = MIPS_PHYS_TO_KSEG0(phys);
bzero((char *)(caddr_t)va + off, size);
mips_dcache_wbinv_range(va + off, size);
} else {
@@ -2388,7 +2432,7 @@ pmap_zero_page_idle(vm_page_t m)
} else
#endif
if (phys < MIPS_KSEG0_LARGEST_PHYS) {
- va = MIPS_PHYS_TO_CACHED(phys);
+ va = MIPS_PHYS_TO_KSEG0(phys);
bzero((caddr_t)va, PAGE_SIZE);
mips_dcache_wbinv_range(va, PAGE_SIZE);
} else {
@@ -2463,9 +2507,9 @@ pmap_copy_page(vm_page_t src, vm_page_t dst)
*/
pmap_flush_pvcache(src);
mips_dcache_wbinv_range_index(
- MIPS_PHYS_TO_CACHED(phy_dst), NBPG);
- va_src = MIPS_PHYS_TO_CACHED(phy_src);
- va_dst = MIPS_PHYS_TO_CACHED(phy_dst);
+ MIPS_PHYS_TO_KSEG0(phy_dst), NBPG);
+ va_src = MIPS_PHYS_TO_KSEG0(phy_src);
+ va_dst = MIPS_PHYS_TO_KSEG0(phy_dst);
bcopy((caddr_t)va_src, (caddr_t)va_dst, PAGE_SIZE);
mips_dcache_wbinv_range(va_dst, PAGE_SIZE);
} else {
@@ -2479,14 +2523,14 @@ pmap_copy_page(vm_page_t src, vm_page_t dst)
int_level = disableintr();
if (phy_src < MIPS_KSEG0_LARGEST_PHYS) {
/* one side needs mapping - dest */
- va_src = MIPS_PHYS_TO_CACHED(phy_src);
+ va_src = MIPS_PHYS_TO_KSEG0(phy_src);
sysm->CMAP2 = mips_paddr_to_tlbpfn(phy_dst) | PTE_RW | PTE_V | PTE_G | PTE_W | PTE_CACHE;
pmap_TLB_update_kernel((vm_offset_t)sysm->CADDR2, sysm->CMAP2);
sysm->valid2 = 1;
va_dst = (vm_offset_t)sysm->CADDR2;
} else if (phy_dst < MIPS_KSEG0_LARGEST_PHYS) {
/* one side needs mapping - src */
- va_dst = MIPS_PHYS_TO_CACHED(phy_dst);
+ va_dst = MIPS_PHYS_TO_KSEG0(phy_dst);
sysm->CMAP1 = mips_paddr_to_tlbpfn(phy_src) | PTE_RW | PTE_V | PTE_G | PTE_W | PTE_CACHE;
pmap_TLB_update_kernel((vm_offset_t)sysm->CADDR1, sysm->CMAP1);
va_src = (vm_offset_t)sysm->CADDR1;
@@ -3168,18 +3212,6 @@ pmap_asid_alloc(pmap)
pmap->pm_asid[PCPU_GET(cpuid)].gen = PCPU_GET(asid_generation);
PCPU_SET(next_asid, PCPU_GET(next_asid) + 1);
}
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW | PDB_TLBPID)) {
- if (curproc)
- printf("pmap_asid_alloc: curproc %d '%s' ",
- curproc->p_pid, curproc->p_comm);
- else
- printf("pmap_asid_alloc: curproc <none> ");
- printf("segtab %p asid %d\n", pmap->pm_segtab,
- pmap->pm_asid[PCPU_GET(cpuid)].asid);
- }
-#endif
}
int
@@ -3248,53 +3280,6 @@ pmap_set_modified(vm_offset_t pa)
PHYS_TO_VM_PAGE(pa)->md.pv_flags |= (PV_TABLE_REF | PV_TABLE_MOD);
}
-#include <machine/db_machdep.h>
-
-/*
- * Dump the translation buffer (TLB) in readable form.
- */
-
-void
-db_dump_tlb(int first, int last)
-{
- struct tlb tlb;
- int tlbno;
-
- tlbno = first;
-
- while (tlbno <= last) {
- MachTLBRead(tlbno, &tlb);
- if (tlb.tlb_lo0 & PTE_V || tlb.tlb_lo1 & PTE_V) {
- printf("TLB %2d vad 0x%08x ", tlbno, (tlb.tlb_hi & 0xffffff00));
- } else {
- printf("TLB*%2d vad 0x%08x ", tlbno, (tlb.tlb_hi & 0xffffff00));
- }
- printf("0=0x%08x ", pfn_to_vad(tlb.tlb_lo0));
- printf("%c", tlb.tlb_lo0 & PTE_M ? 'M' : ' ');
- printf("%c", tlb.tlb_lo0 & PTE_G ? 'G' : ' ');
- printf(" atr %x ", (tlb.tlb_lo0 >> 3) & 7);
- printf("1=0x%08x ", pfn_to_vad(tlb.tlb_lo1));
- printf("%c", tlb.tlb_lo1 & PTE_M ? 'M' : ' ');
- printf("%c", tlb.tlb_lo1 & PTE_G ? 'G' : ' ');
- printf(" atr %x ", (tlb.tlb_lo1 >> 3) & 7);
- printf(" sz=%x pid=%x\n", tlb.tlb_mask,
- (tlb.tlb_hi & 0x000000ff)
- );
- tlbno++;
- }
-}
-
-#ifdef DDB
-#include <sys/kernel.h>
-#include <ddb/ddb.h>
-
-DB_SHOW_COMMAND(tlb, ddb_dump_tlb)
-{
- db_dump_tlb(0, num_tlbentries - 1);
-}
-
-#endif
-
/*
* Routine: pmap_kextract
* Function:
@@ -3306,7 +3291,7 @@ pmap_kextract(vm_offset_t va)
{
vm_offset_t pa = 0;
- if (va < MIPS_CACHED_MEMORY_ADDR) {
+ if (va < MIPS_KSEG0_START) {
/* user virtual address */
pt_entry_t *ptep;
@@ -3316,16 +3301,16 @@ pmap_kextract(vm_offset_t va)
pa = mips_tlbpfn_to_paddr(*ptep) |
(va & PAGE_MASK);
}
- } else if (va >= MIPS_CACHED_MEMORY_ADDR &&
- va < MIPS_UNCACHED_MEMORY_ADDR)
- pa = MIPS_CACHED_TO_PHYS(va);
- else if (va >= MIPS_UNCACHED_MEMORY_ADDR &&
+ } else if (va >= MIPS_KSEG0_START &&
+ va < MIPS_KSEG1_START)
+ pa = MIPS_KSEG0_TO_PHYS(va);
+ else if (va >= MIPS_KSEG1_START &&
va < MIPS_KSEG2_START)
- pa = MIPS_UNCACHED_TO_PHYS(va);
+ pa = MIPS_KSEG1_TO_PHYS(va);
#ifdef VM_ALLOC_WIRED_TLB_PG_POOL
else if (need_wired_tlb_page_pool && ((va >= VM_MIN_KERNEL_ADDRESS) &&
(va < (VM_MIN_KERNEL_ADDRESS + VM_KERNEL_ALLOC_OFFSET))))
- pa = MIPS_CACHED_TO_PHYS(va);
+ pa = MIPS_KSEG0_TO_PHYS(va);
#endif
else if (va >= MIPS_KSEG2_START && va < VM_MAX_KERNEL_ADDRESS) {
pt_entry_t *ptep;
@@ -3377,3 +3362,61 @@ pmap_flush_pvcache(vm_page_t m)
}
}
}
+
+void
+pmap_save_tlb(void)
+{
+ int tlbno, cpu;
+
+ cpu = PCPU_GET(cpuid);
+
+ for (tlbno = 0; tlbno < num_tlbentries; ++tlbno)
+ MachTLBRead(tlbno, &tlbstash[cpu][tlbno]);
+}
+
+#ifdef DDB
+#include <ddb/ddb.h>
+
+DB_SHOW_COMMAND(tlb, ddb_dump_tlb)
+{
+ int cpu, tlbno;
+ struct tlb *tlb;
+
+ if (have_addr)
+ cpu = ((addr >> 4) % 16) * 10 + (addr % 16);
+ else
+ cpu = PCPU_GET(cpuid);
+
+ if (cpu < 0 || cpu >= mp_ncpus) {
+ db_printf("Invalid CPU %d\n", cpu);
+ return;
+ } else
+ db_printf("CPU %d:\n", cpu);
+
+ if (cpu == PCPU_GET(cpuid))
+ pmap_save_tlb();
+
+ for (tlbno = 0; tlbno < num_tlbentries; ++tlbno) {
+ tlb = &tlbstash[cpu][tlbno];
+ if (tlb->tlb_lo0 & PTE_V || tlb->tlb_lo1 & PTE_V) {
+ printf("TLB %2d vad 0x%0lx ",
+ tlbno, (long)(tlb->tlb_hi & 0xffffff00));
+ } else {
+ printf("TLB*%2d vad 0x%0lx ",
+ tlbno, (long)(tlb->tlb_hi & 0xffffff00));
+ }
+ printf("0=0x%0lx ", pfn_to_vad((long)tlb->tlb_lo0));
+ printf("%c", tlb->tlb_lo0 & PTE_V ? 'V' : '-');
+ printf("%c", tlb->tlb_lo0 & PTE_M ? 'M' : '-');
+ printf("%c", tlb->tlb_lo0 & PTE_G ? 'G' : '-');
+ printf(" atr %x ", (tlb->tlb_lo0 >> 3) & 7);
+ printf("1=0x%0lx ", pfn_to_vad((long)tlb->tlb_lo1));
+ printf("%c", tlb->tlb_lo1 & PTE_V ? 'V' : '-');
+ printf("%c", tlb->tlb_lo1 & PTE_M ? 'M' : '-');
+ printf("%c", tlb->tlb_lo1 & PTE_G ? 'G' : '-');
+ printf(" atr %x ", (tlb->tlb_lo1 >> 3) & 7);
+ printf(" sz=%x pid=%x\n", tlb->tlb_mask,
+ (tlb->tlb_hi & 0x000000ff));
+ }
+}
+#endif /* DDB */
diff --git a/sys/mips/mips/support.S b/sys/mips/mips/support.S
index 6282eb0..2aed3e6 100644
--- a/sys/mips/mips/support.S
+++ b/sys/mips/mips/support.S
@@ -51,6 +51,38 @@
*/
/*
+ * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jonathan R. Stone for
+ * the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
* Contains code that is the first executed at boot time plus
* assembly language support routines.
*/
@@ -61,6 +93,7 @@
#include <machine/asm.h>
#include <machine/cpu.h>
#include <machine/regnum.h>
+#include <machine/cpuregs.h>
#include "assym.s"
@@ -1586,3 +1619,78 @@ LEAF(octeon_get_control)
.set mips0
END(octeon_get_control)
#endif
+
+LEAF(mips3_ld)
+ .set push
+ .set noreorder
+ .set mips64
+#if defined(__mips_o32)
+ mfc0 t0, MIPS_COP_0_STATUS # turn off interrupts
+ and t1, t0, ~(MIPS_SR_INT_IE)
+ mtc0 t1, MIPS_COP_0_STATUS
+ COP0_SYNC
+ nop
+ nop
+ nop
+
+ ld v0, 0(a0)
+#if _BYTE_ORDER == _BIG_ENDIAN
+ dsll v1, v0, 32
+ dsra v1, v1, 32 # low word in v1
+ dsra v0, v0, 32 # high word in v0
+#else
+ dsra v1, v0, 32 # high word in v1
+ dsll v0, v0, 32
+ dsra v0, v0, 32 # low word in v0
+#endif
+
+ mtc0 t0, MIPS_COP_0_STATUS # restore intr status.
+ COP0_SYNC
+ nop
+#else /* !__mips_o32 */
+ ld v0, 0(a0)
+#endif /* !__mips_o32 */
+
+ jr ra
+ nop
+ .set pop
+END(mips3_ld)
+
+LEAF(mips3_sd)
+ .set push
+ .set mips64
+ .set noreorder
+#if defined(__mips_o32)
+ mfc0 t0, MIPS_COP_0_STATUS # turn off interrupts
+ and t1, t0, ~(MIPS_SR_INT_IE)
+ mtc0 t1, MIPS_COP_0_STATUS
+ COP0_SYNC
+ nop
+ nop
+ nop
+
+ # NOTE: a1 is padding!
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+ dsll a2, a2, 32 # high word in a2
+ dsll a3, a3, 32 # low word in a3
+ dsrl a3, a3, 32
+#else
+ dsll a2, a2, 32 # low word in a2
+ dsrl a2, a2, 32
+ dsll a3, a3, 32 # high word in a3
+#endif
+ or a1, a2, a3
+ sd a1, 0(a0)
+
+ mtc0 t0, MIPS_COP_0_STATUS # restore intr status.
+ COP0_SYNC
+ nop
+#else /* !__mips_o32 */
+ sd a1, 0(a0)
+#endif /* !__mips_o32 */
+
+ jr ra
+ nop
+ .set pop
+END(mips3_sd)
diff --git a/sys/mips/mips/swtch.S b/sys/mips/mips/swtch.S
index 1248276..dd66ece 100644
--- a/sys/mips/mips/swtch.S
+++ b/sys/mips/mips/swtch.S
@@ -245,6 +245,14 @@ LEAF(savectx)
SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0)
SAVE_U_PCB_CONTEXT(v0, PREG_SR, a0)
SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0)
+
+ move v0, ra /* save 'ra' before we trash it */
+ jal 1f
+ nop
+1:
+ SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0)
+ move ra, v0 /* restore 'ra' before returning */
+
/*
* FREEBSD_DEVELOPERS_FIXME:
* In case there are CPU-specific registers that need
diff --git a/sys/mips/mips/tick.c b/sys/mips/mips/tick.c
index bf147c5..60b3511 100644
--- a/sys/mips/mips/tick.c
+++ b/sys/mips/mips/tick.c
@@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$");
uint64_t counter_freq;
+struct timecounter *platform_timecounter;
+
static uint64_t cycles_per_tick;
static uint64_t cycles_per_usec;
static uint64_t cycles_per_hz, cycles_per_stathz, cycles_per_profhz;
@@ -61,17 +63,14 @@ static uint64_t cycles_per_hz, cycles_per_stathz, cycles_per_profhz;
static u_int32_t counter_upper = 0;
static u_int32_t counter_lower_last = 0;
-struct clk_ticks
-{
+struct clk_ticks {
u_long hard_ticks;
u_long stat_ticks;
u_long prof_ticks;
- /*
- * pad for cache line alignment of pcpu info
- * cache-line-size - number of used bytes
- */
- char pad[32-(3*sizeof (u_long))];
-} static pcpu_ticks[MAXCPU];
+ uint32_t compare_ticks;
+} __aligned(CACHE_LINE_SIZE);
+
+static struct clk_ticks pcpu_ticks[MAXCPU];
/*
* Device methods
@@ -103,6 +102,9 @@ platform_initclocks(void)
{
tc_init(&counter_timecounter);
+
+ if (platform_timecounter != NULL)
+ tc_init(platform_timecounter);
}
static uint64_t
@@ -255,25 +257,47 @@ clock_intr(void *arg)
{
struct clk_ticks *cpu_ticks;
struct trapframe *tf;
- uint32_t ltick;
+ uint32_t count, compare, delta;
+
+ cpu_ticks = &pcpu_ticks[PCPU_GET(cpuid)];
+
/*
* Set next clock edge.
*/
- ltick = mips_rd_count();
- mips_wr_compare(ltick + cycles_per_tick);
- cpu_ticks = &pcpu_ticks[PCPU_GET(cpuid)];
+ count = mips_rd_count();
+ compare = cpu_ticks->compare_ticks;
+ cpu_ticks->compare_ticks = count + cycles_per_tick;
+ mips_wr_compare(cpu_ticks->compare_ticks);
critical_enter();
- if (ltick < counter_lower_last) {
+ if (count < counter_lower_last) {
counter_upper++;
- counter_lower_last = ltick;
+ counter_lower_last = count;
}
/*
* Magic. Setting up with an arg of NULL means we get passed tf.
*/
tf = (struct trapframe *)arg;
+ delta = cycles_per_tick;
+
+ /*
+ * Account for the "lost time" between when the timer interrupt fired
+ * and when 'clock_intr' actually started executing.
+ */
+ delta += count - compare;
+
+ /*
+ * If the COUNT and COMPARE registers are no longer in sync then make
+ * up some reasonable value for the 'delta'.
+ *
+ * This could happen, for e.g., after we resume normal operations after
+ * exiting the debugger.
+ */
+ if (delta > cycles_per_hz)
+ delta = cycles_per_hz;
+
/* Fire hardclock at hz. */
- cpu_ticks->hard_ticks += cycles_per_tick;
+ cpu_ticks->hard_ticks += delta;
if (cpu_ticks->hard_ticks >= cycles_per_hz) {
cpu_ticks->hard_ticks -= cycles_per_hz;
if (PCPU_GET(cpuid) == 0)
@@ -283,14 +307,14 @@ clock_intr(void *arg)
}
/* Fire statclock at stathz. */
- cpu_ticks->stat_ticks += cycles_per_tick;
+ cpu_ticks->stat_ticks += delta;
if (cpu_ticks->stat_ticks >= cycles_per_stathz) {
cpu_ticks->stat_ticks -= cycles_per_stathz;
statclock(USERMODE(tf->sr));
}
/* Fire profclock at profhz, but only when needed. */
- cpu_ticks->prof_ticks += cycles_per_tick;
+ cpu_ticks->prof_ticks += delta;
if (cpu_ticks->prof_ticks >= cycles_per_profhz) {
cpu_ticks->prof_ticks -= cycles_per_profhz;
if (profprocs != 0)
diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c
index 5fdfabd..124087c 100644
--- a/sys/mips/mips/trap.c
+++ b/sys/mips/mips/trap.c
@@ -118,8 +118,8 @@ void (*machExceptionTable[]) (void)= {
*/
MipsKernIntr, /* external interrupt */
MipsKernGenException, /* TLB modification */
- MipsKernTLBInvalidException, /* TLB miss (load or instr. fetch) */
- MipsKernTLBInvalidException, /* TLB miss (store) */
+ MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */
+ MipsTLBInvalidException,/* TLB miss (store) */
MipsKernGenException, /* address error (load or I-fetch) */
MipsKernGenException, /* address error (store) */
MipsKernGenException, /* bus error (I-fetch) */
@@ -153,8 +153,8 @@ void (*machExceptionTable[]) (void)= {
*/
MipsUserIntr, /* 0 */
MipsUserGenException, /* 1 */
- MipsUserTLBInvalidException, /* 2 */
- MipsUserTLBInvalidException, /* 3 */
+ MipsTLBInvalidException,/* 2 */
+ MipsTLBInvalidException,/* 3 */
MipsUserGenException, /* 4 */
MipsUserGenException, /* 5 */
MipsUserGenException, /* 6 */
diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c
index f76dc4d..3f8e6cc 100644
--- a/sys/mips/mips/vm_machdep.c
+++ b/sys/mips/mips/vm_machdep.c
@@ -214,6 +214,16 @@ cpu_thread_swapin(struct thread *td)
{
pt_entry_t *pte;
int i;
+ vm_offset_t unused_kstack_page;
+
+ /*
+ * Unmap the unused kstack page.
+ */
+ unused_kstack_page = td->td_kstack;
+ if (td->td_md.md_realstack == td->td_kstack)
+ unused_kstack_page += (KSTACK_PAGES - 1) * PAGE_SIZE;
+
+ pmap_kremove(unused_kstack_page);
/*
* The kstack may be at a different physical address now.
@@ -239,13 +249,19 @@ cpu_thread_swapout(struct thread *td)
void
cpu_thread_alloc(struct thread *td)
{
+ vm_offset_t unused_kstack_page;
pt_entry_t *pte;
int i;
- if(td->td_kstack & (1 << PAGE_SHIFT))
+ if (td->td_kstack & (1 << PAGE_SHIFT)) {
td->td_md.md_realstack = td->td_kstack + PAGE_SIZE;
- else
+ unused_kstack_page = td->td_kstack;
+ } else {
td->td_md.md_realstack = td->td_kstack;
+ unused_kstack_page = td->td_kstack +
+ (KSTACK_PAGES - 1) * PAGE_SIZE;
+ }
+ pmap_kremove(unused_kstack_page);
td->td_pcb = (struct pcb *)(td->td_md.md_realstack +
(td->td_kstack_pages - 1) * PAGE_SIZE) - 1;
diff --git a/sys/mips/sibyte/sb_asm.S b/sys/mips/sibyte/sb_asm.S
index a822d79..312d3a5 100644
--- a/sys/mips/sibyte/sb_asm.S
+++ b/sys/mips/sibyte/sb_asm.S
@@ -28,61 +28,11 @@
#include <machine/asm.h>
#include <machine/cpuregs.h>
-#include <machine/endian.h>
-
-/*
- * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit
- * processor. It has some registers that must be accessed using 64-bit load
- * and store instructions.
- *
- * So we have to resort to assembly because the compiler does not emit the
- * 'ld' and 'sd' instructions since it thinks that it is compiling for a
- * 32-bit mips processor.
- */
.set mips64
.set noat
.set noreorder
-/*
- * Parameters: uint32_t ptr
- * Return value: *(uint64_t *)ptr
- */
-LEAF(sb_load64)
- ld v1, 0(a0) /* result = *(uint64_t *)ptr */
- move v0, v1
-#if _BYTE_ORDER == _BIG_ENDIAN
- dsll32 v1, v1, 0
- dsrl32 v1, v1, 0 /* v1 = lower_uint32(result) */
- jr ra
- dsrl32 v0, v0, 0 /* v0 = upper_uint32(result) */
-#else
- dsll32 v0, v0, 0
- dsrl32 v0, v0, 0 /* v0 = lower_uint32(result) */
- jr ra
- dsrl32 v1, v1, 0 /* v1 = upper_uint32(result) */
-#endif
-END(sb_load64)
-
-/*
- * Parameters: uint32_t ptr, uint64_t val
- * Return value: void
- */
-LEAF(sb_store64)
-#if _BYTE_ORDER == _BIG_ENDIAN
- dsll32 a2, a2, 0 /* a2 = upper_uint32(val) */
- dsll32 a3, a3, 0 /* a3 = lower_uint32(val) */
- dsrl32 a3, a3, 0
-#else
- dsll32 a3, a3, 0 /* a3 = upper_uint32(val) */
- dsll32 a2, a2, 0 /* a2 = lower_uint32(val) */
- dsrl32 a2, a2, 0
-#endif
- or t0, a2, a3
- jr ra
- sd t0, 0(a0)
-END(sb_store64)
-
#ifdef SMP
/*
* This function must be implemented in assembly because it is called early
diff --git a/sys/mips/sibyte/sb_machdep.c b/sys/mips/sibyte/sb_machdep.c
index 8f59815..dca2869 100644
--- a/sys/mips/sibyte/sb_machdep.c
+++ b/sys/mips/sibyte/sb_machdep.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/user.h>
+#include <sys/timetc.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
@@ -364,6 +365,32 @@ platform_start_ap(int cpuid)
}
#endif /* SMP */
+static u_int
+sb_get_timecount(struct timecounter *tc)
+{
+
+ return ((u_int)sb_zbbus_cycle_count());
+}
+
+static void
+sb_timecounter_init(void)
+{
+ static struct timecounter sb_timecounter = {
+ sb_get_timecount,
+ NULL,
+ ~0u,
+ 0,
+ "sibyte_zbbus_counter",
+ 2000
+ };
+
+ /*
+ * The ZBbus cycle counter runs at half the cpu frequency.
+ */
+ sb_timecounter.tc_frequency = sb_cpu_speed() / 2;
+ platform_timecounter = &sb_timecounter;
+}
+
void
platform_start(__register_t a0, __register_t a1, __register_t a2,
__register_t a3)
@@ -378,6 +405,7 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
mips_postboot_fixup();
sb_intr_init(0);
+ sb_timecounter_init();
/* Initialize pcpu stuff */
mips_pcpu0_init();
@@ -400,4 +428,6 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
mips_init();
mips_timer_init_params(sb_cpu_speed(), 0);
+
+ set_cputicker(sb_zbbus_cycle_count, sb_cpu_speed() / 2, 1);
}
diff --git a/sys/mips/sibyte/sb_scd.c b/sys/mips/sibyte/sb_scd.c
index 007e149..bfaa8d4 100644
--- a/sys/mips/sibyte/sb_scd.c
+++ b/sys/mips/sibyte/sb_scd.c
@@ -38,8 +38,15 @@ __FBSDID("$FreeBSD$");
#include "sb_scd.h"
-extern void sb_store64(uint32_t addr, uint64_t val);
-extern uint64_t sb_load64(uint32_t addr);
+/*
+ * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit
+ * processor. It has some registers that must be accessed using 64-bit load
+ * and store instructions.
+ *
+ * We use the mips_ld() and mips_sd() functions to do this for us.
+ */
+#define sb_store64(addr, val) mips3_sd((uint64_t *)(addr), (val))
+#define sb_load64(addr) mips3_ld((uint64_t *)(addr))
/*
* System Control and Debug (SCD) unit on the Sibyte ZBbus.
@@ -56,6 +63,8 @@ extern uint64_t sb_load64(uint32_t addr);
#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008)
#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5)
+#define ZBBUS_CYCLE_COUNT_ADDR MIPS_PHYS_TO_KSEG1(0x10030000)
+
#define INTSRC_MASK_ADDR(cpu) \
(MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13))
@@ -83,6 +92,13 @@ sb_write_syscfg(uint64_t val)
}
uint64_t
+sb_zbbus_cycle_count(void)
+{
+
+ return (sb_load64(ZBBUS_CYCLE_COUNT_ADDR));
+}
+
+uint64_t
sb_cpu_speed(void)
{
int plldiv;
diff --git a/sys/mips/sibyte/sb_scd.h b/sys/mips/sibyte/sb_scd.h
index 03d2681..f8bb6e4 100644
--- a/sys/mips/sibyte/sb_scd.h
+++ b/sys/mips/sibyte/sb_scd.h
@@ -31,6 +31,7 @@
#define NUM_INTSRC 64 /* total number of interrupt sources */
+uint64_t sb_zbbus_cycle_count(void);
uint64_t sb_cpu_speed(void);
void sb_system_reset(void);
OpenPOWER on IntegriCloud