From owner-svn-src-head@FreeBSD.ORG Sat Apr 17 03:08:13 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8050E106564A; Sat, 17 Apr 2010 03:08:13 +0000 (UTC) (envelope-from jmallett@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6CEFF8FC14; Sat, 17 Apr 2010 03:08:13 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o3H38DuT028614; Sat, 17 Apr 2010 03:08:13 GMT (envelope-from jmallett@svn.freebsd.org) Received: (from jmallett@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o3H38DMI028603; Sat, 17 Apr 2010 03:08:13 GMT (envelope-from jmallett@svn.freebsd.org) Message-Id: <201004170308.o3H38DMI028603@svn.freebsd.org> From: Juli Mallett Date: Sat, 17 Apr 2010 03:08:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r206721 - in head/sys/mips: cavium cavium/dev/rgmii mips X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 Apr 2010 03:08:13 -0000 Author: jmallett Date: Sat Apr 17 03:08:13 2010 New Revision: 206721 URL: http://svn.freebsd.org/changeset/base/206721 Log: o) Add SMP support for Octeon using U-Boot to launch all the processors at the same time. o) Remove some unused trivial uart functions from octeon_machdep now that the uart part is fully working and they are unused. o) Use __func__ instead of __FUNCTION__. o) Use intr_*() instead of other routines that do the same thing. o) Remove some duplicate printfs from the Octeon port, as well as duplicate setting of Maxmem. o) Use the right frequency divider on Octeon. o) Use PCPU_GET(cpuid) consistently to get the cpuid of the running core. o) Remove some unused macros in the Octeon port. o) Use mips_sync() around use of the global dpcpu, whose value may not be visible to APs at first. o) When loading the first thread's stack, use macros to make the code correct for n64 as well. o) Remove stub, do-nothing FAU init/enable/disable functions from the RGMX driver. Added: head/sys/mips/cavium/octeon_mp.c (contents, props changed) Deleted: head/sys/mips/cavium/dev/rgmii/octeon_fau.c Modified: head/sys/mips/cavium/asm_octeon.S head/sys/mips/cavium/dev/rgmii/octeon_fau.h head/sys/mips/cavium/dev/rgmii/octeon_rgmx.c head/sys/mips/cavium/files.octeon1 head/sys/mips/cavium/octeon_machdep.c head/sys/mips/cavium/octeon_pcmap_regs.h head/sys/mips/mips/locore.S head/sys/mips/mips/mp_machdep.c head/sys/mips/mips/mpboot.S Modified: head/sys/mips/cavium/asm_octeon.S ============================================================================== --- head/sys/mips/cavium/asm_octeon.S Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/cavium/asm_octeon.S Sat Apr 17 03:08:13 2010 (r206721) @@ -1,182 +1,66 @@ -/***********************license start*************** - * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights - * reserved. +/*- + * Copyright (c) 2004-2010 Juli Mallett + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * 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. - * - * * Neither the name of Cavium Networks nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS - * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH - * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY - * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT - * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES - * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR - * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET - * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT - * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. - * - * - * For any questions regarding licensing please contact marketing@caviumnetworks.com - * - ***********************license end**************************************/ - -/* $FreeBSD$ */ + * $FreeBSD$ + */ #include -#include -#include -#include -#include - -#include "assym.s" - - -#define CPU_DISABLE_INTERRUPTS(reg, reg2, reg3) \ - mfc0 reg, MIPS_COP_0_STATUS; \ - nop; \ - move reg3, reg; \ - li reg2, ~MIPS_SR_INT_IE; \ - and reg, reg2, reg; \ - mtc0 reg, MIPS_COP_0_STATUS; \ - COP0_SYNC + .set noreorder - - -#define CPU_ENABLE_INTERRUPTS(reg, reg3) \ - mfc0 reg, MIPS_COP_0_STATUS; \ - nop; \ - or reg, reg, reg3; \ - mtc0 reg, MIPS_COP_0_STATUS; \ - COP0_SYNC - - -#define PUSHR(reg) \ - addiu sp,sp,-16 ; \ - sd reg, 8(sp) ; \ - nop ; - -#define POPR(reg) \ - ld reg, 8(sp) ; \ - addiu sp,sp,16 ; \ - nop ; - - - - +#ifdef SMP /* - * octeon_ciu_get_interrupt_reg_addr - * - * Given Int-X, En-X combination, return the CIU Interrupt Enable Register addr - * a0 = ciu Int-X: 0/1 - * a1 = ciu EN-0: 0/1 + * This function must be implemented in assembly because it is called early + * in AP boot without a valid stack. */ -LEAF(octeon_ciu_get_interrupt_reg_addr) - .set noreorder - .set mips3 - - beqz a0, ciu_get_interrupt_reg_addr_Int_0 - nop - -ciu_get_interrupt_reg_addr_Int_1: - beqz a1, ciu_get_interrupt_reg_addr_Int_1_En_0 - nop - -ciu_get_interrupt_reg_addr_Int_1_En1: - li a0, OCTEON_CIU_ADDR_HI - dsll32 a0, a0, 0 - nop - ori a0, OCTEON_CIU_EN1_INT1_LO - j ciu_get_interrupt_reg_addr_ret - nop - -ciu_get_interrupt_reg_addr_Int_1_En_0: - li a0, OCTEON_CIU_ADDR_HI - dsll32 a0, a0, 0 - nop - ori a0, OCTEON_CIU_EN0_INT1_LO - j ciu_get_interrupt_reg_addr_ret - nop - -ciu_get_interrupt_reg_addr_Int_0: - beqz a1, ciu_get_interrupt_reg_addr_Int_0_En_0 - nop - -ciu_get_interrupt_reg_addr_Int_0_En_1: - li a0, OCTEON_CIU_ADDR_HI - dsll32 a0, a0, 0 - nop - ori a0, OCTEON_CIU_EN1_INT0_LO - j ciu_get_interrupt_reg_addr_ret - nop - -ciu_get_interrupt_reg_addr_Int_0_En_0: - li a0, OCTEON_CIU_ADDR_HI - dsll32 a0, a0, 0 - nop - ori a0, OCTEON_CIU_EN0_INT0_LO - - -ciu_get_interrupt_reg_addr_ret: - j ra - nop - - .set mips0 - .set reorder -END(octeon_ciu_get_interrupt_reg_addr) +LEAF(platform_processor_id) + .set push + .set mips32r2 + jr ra + rdhwr v0, $0 + .set pop +END(platform_processor_id) - - /* - * octeon_ciu_mask_all_interrupts - * - * a0 = ciu Interrupt-X: 0/1 - * a1 = ciu Enable-X: 0/1 + * Called on APs to wait until they are told to launch. */ -LEAF(octeon_ciu_mask_all_interrupts) - .set noreorder - .set mips3 - - PUSHR(ra) - PUSHR(s0) - - move t0, a0 - move t1, a1 - li a0, MIPS_SR_INT_IE - CPU_DISABLE_INTERRUPTS(a2, a1, s0) - move a0, t0 - move t1, a1 - jal octeon_ciu_get_interrupt_reg_addr - nop - ld a2, 0(a0) # Dummy read - nop - move a2, zero # Clear all - sd a2, 0(a0) # Write new Enable bits - nop - CPU_ENABLE_INTERRUPTS(a2, s0) - - POPR(s0) - POPR(ra) - j ra # Return - nop # (bd slot) - - .set mips0 - .set reorder -END(octeon_ciu_mask_all_interrupts) - +LEAF(octeon_ap_wait) + jal platform_processor_id + nop + +1: ll t0, octeon_ap_boot + bne v0, t0, 1b + nop + + move t0, zero + sc t0, octeon_ap_boot + + beqz t0, 1b + nop + + j mpentry + nop +END(octeon_ap_wait) +#endif Modified: head/sys/mips/cavium/dev/rgmii/octeon_fau.h ============================================================================== --- head/sys/mips/cavium/dev/rgmii/octeon_fau.h Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/cavium/dev/rgmii/octeon_fau.h Sat Apr 17 03:08:13 2010 (r206721) @@ -217,9 +217,4 @@ static inline void octeon_fau_atomic_add } -extern void octeon_fau_init(void); -extern void octeon_fau_enable(void); -extern void octeon_fau_disable(void); - - #endif /* ___OCTEON_FAU__H___ */ Modified: head/sys/mips/cavium/dev/rgmii/octeon_rgmx.c ============================================================================== --- head/sys/mips/cavium/dev/rgmii/octeon_rgmx.c Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/cavium/dev/rgmii/octeon_rgmx.c Sat Apr 17 03:08:13 2010 (r206721) @@ -1481,7 +1481,7 @@ static void octeon_config_hw_units_post_ oct_write64(OCTEON_POW_WORKQUEUE_INT_THRESHOLD(OCTEON_POW_RX_GROUP_NUM), thr.word64); #endif - ciu_enable_interrupts(OCTEON_CORE_ID, OCTEON_RGMX_CIU_INTX, OCTEON_RGMX_CIU_ENX, + ciu_enable_interrupts(PCPU_GET(cpuid), OCTEON_RGMX_CIU_INTX, OCTEON_RGMX_CIU_ENX, (OCTEON_POW_RX_GROUP_MASK | CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1)), CIU_MIPS_IP2); Modified: head/sys/mips/cavium/files.octeon1 ============================================================================== --- head/sys/mips/cavium/files.octeon1 Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/cavium/files.octeon1 Sat Apr 17 03:08:13 2010 (r206721) @@ -1,8 +1,7 @@ # $FreeBSD$ # Octeon Support Files # -mips/mips/mp_machdep.c optional smp -mips/cavium/dev/rgmii/octeon_fau.c optional rgmii +mips/cavium/asm_octeon.S optional smp mips/cavium/dev/rgmii/octeon_fpa.c optional rgmii mips/cavium/dev/rgmii/octeon_ipd.c optional rgmii mips/cavium/dev/rgmii/octeon_pko.c optional rgmii @@ -10,6 +9,7 @@ mips/cavium/dev/rgmii/octeon_rgmx.c opt mips/cavium/obio.c optional uart mips/cavium/octeon_ebt3000_cf.c optional cf mips/cavium/octeon_machdep.c standard +mips/cavium/octeon_mp.c optional smp mips/cavium/uart_bus_octeonusart.c optional uart mips/cavium/uart_cpu_octeonusart.c optional uart mips/cavium/uart_dev_oct16550.c optional uart Modified: head/sys/mips/cavium/octeon_machdep.c ============================================================================== --- head/sys/mips/cavium/octeon_machdep.c Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/cavium/octeon_machdep.c Sat Apr 17 03:08:13 2010 (r206721) @@ -111,25 +111,6 @@ platform_reset(void) oct_write64(OCTEON_CIU_SOFT_RST, 1); } - -static inline uint32_t -octeon_disable_interrupts(void) -{ - uint32_t status_bits; - - status_bits = mips_rd_status(); - mips_wr_status(status_bits & ~MIPS_SR_INT_IE); - return (status_bits); -} - - -static inline void -octeon_set_interrupts(uint32_t status_bits) -{ - mips_wr_status(status_bits); -} - - void octeon_led_write_char(int char_position, char val) { @@ -203,82 +184,6 @@ octeon_led_run_wheel(int *prog_count, in *prog_count &= 0x7; } -#define LSR_DATAREADY 0x01 /* Data ready */ -#define LSR_THRE 0x20 /* Transmit holding register empty */ -#define LSR_TEMT 0x40 /* Transmitter Empty. THR, TSR & FIFO */ -#define USR_TXFIFO_NOTFULL 0x02 /* Uart TX FIFO Not full */ - -/* - * octeon_uart_write_byte - * - * Put out a single byte off of uart port. - */ - -void -octeon_uart_write_byte(int uart_index, uint8_t ch) -{ - uint64_t val, val2; - if (uart_index < 0 || uart_index > 1) - return; - - while (1) { - val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); - val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400)); - if ((((uint8_t) val) & LSR_THRE) || - (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { - break; - } - } - - /* Write the byte */ - oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch); - - /* Force Flush the IOBus */ - oct_read64(OCTEON_MIO_BOOT_BIST_STAT); -} - - -void -octeon_uart_write_byte0(uint8_t ch) -{ - uint64_t val, val2; - - while (1) { - val = oct_read64(OCTEON_MIO_UART0_LSR); - val2 = oct_read64(OCTEON_MIO_UART0_USR); - if ((((uint8_t) val) & LSR_THRE) || - (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { - break; - } - } - - /* Write the byte */ - oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch); - - /* Force Flush the IOBus */ - oct_read64(OCTEON_MIO_BOOT_BIST_STAT); -} - -/* - * octeon_uart_write_string - * - */ -void -octeon_uart_write_string(int uart_index, const char *str) -{ - /* Just loop writing one byte at a time */ - - while (*str) { - octeon_uart_write_byte(uart_index, *str); - if (*str == '\n') { - octeon_uart_write_byte(uart_index, '\r'); - } - str++; - } -} - -static char wstr[30]; - void octeon_led_write_hex(uint32_t wl) { @@ -289,44 +194,6 @@ octeon_led_write_hex(uint32_t wl) } -void octeon_uart_write_hex2(uint32_t wl, uint32_t wh) -{ - sprintf(wstr, "0x%X-0x%X ", wh, wl); - octeon_uart_write_string(0, wstr); -} - -void -octeon_uart_write_hex(uint32_t wl) -{ - sprintf(wstr, " 0x%X ", wl); - octeon_uart_write_string(0, wstr); -} - -/* - * octeon_wait_uart_flush - */ -void -octeon_wait_uart_flush(int uart_index, uint8_t ch) -{ - uint64_t val; - int64_t val3; - uint32_t cpu_status_bits; - - if (uart_index < 0 || uart_index > 1) - return; - - cpu_status_bits = octeon_disable_interrupts(); - /* Force Flush the IOBus */ - oct_read64(OCTEON_MIO_BOOT_BIST_STAT); - for (val3 = 0xfffffffff; val3 > 0; val3--) { - val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); - if (((uint8_t) val) & LSR_TEMT) - break; - } - octeon_set_interrupts(cpu_status_bits); -} - - /* * octeon_debug_symbol * @@ -450,17 +317,17 @@ ciu_get_en_reg_addr_new(int corenum, int /* XXX kasserts? */ if (enx < CIU_EN_0 || enx > CIU_EN_1) { printf("%s: invalid enx value %d, should be %d or %d\n", - __FUNCTION__, enx, CIU_EN_0, CIU_EN_1); + __func__, enx, CIU_EN_0, CIU_EN_1); return 0; } if (intx < CIU_INT_0 || intx > CIU_INT_1) { printf("%s: invalid intx value %d, should be %d or %d\n", - __FUNCTION__, enx, CIU_INT_0, CIU_INT_1); + __func__, enx, CIU_INT_0, CIU_INT_1); return 0; } if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) { printf("%s: invalid ciu_ip value %d, should be %d or %d\n", - __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3); + __func__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3); return 0; } @@ -517,7 +384,7 @@ ciu_clear_int_summary(int core_num, int core_num, intx, enx, write_bits); #endif - cpu_status_bits = octeon_disable_interrupts(); + cpu_status_bits = intr_disable(); ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); @@ -535,7 +402,7 @@ ciu_clear_int_summary(int core_num, int printf(" Readback: 0x%llX\n\n ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr)); #endif - octeon_set_interrupts(cpu_status_bits); + intr_restore(cpu_status_bits); } /* @@ -550,7 +417,7 @@ ciu_disable_intr(int core_num, int intx, if (core_num == CIU_THIS_CORE) core_num = octeon_get_core_num(); - cpu_status_bits = octeon_disable_interrupts(); + cpu_status_bits = intr_disable(); ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); @@ -559,7 +426,7 @@ ciu_disable_intr(int core_num, int intx, oct_write64(ciu_intr_reg_addr, 0LL); oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ - octeon_set_interrupts(cpu_status_bits); + intr_restore(cpu_status_bits); } void @@ -580,7 +447,7 @@ ciu_dump_interrutps_enabled(int core_num #endif if (!ciu_intr_reg_addr) { - printf("Bad call to %s\n", __FUNCTION__); + printf("Bad call to %s\n", __func__); while(1); return; } @@ -612,7 +479,7 @@ void ciu_enable_interrupts(int core_num, core_num, intx, enx, ciu_ip, set_these_interrupt_bits); #endif - cpu_status_bits = octeon_disable_interrupts(); + cpu_status_bits = intr_disable(); #ifndef OCTEON_SMP_1 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); @@ -621,7 +488,7 @@ void ciu_enable_interrupts(int core_num, #endif if (!ciu_intr_reg_addr) { - printf("Bad call to %s\n", __FUNCTION__); + printf("Bad call to %s\n", __func__); while(1); return; /* XXX */ } @@ -634,7 +501,7 @@ void ciu_enable_interrupts(int core_num, #endif ciu_intr_bits |= set_these_interrupt_bits; oct_write64(ciu_intr_reg_addr, ciu_intr_bits); -#ifdef OCTEON_SMP +#ifdef SMP mips_wbflush(); #endif oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ @@ -644,7 +511,7 @@ void ciu_enable_interrupts(int core_num, (uint64_t)oct_read64(ciu_intr_reg_addr)); #endif - octeon_set_interrupts(cpu_status_bits); + intr_restore(cpu_status_bits); } unsigned long @@ -659,12 +526,8 @@ octeon_memory_init(void) uint32_t realmem_bytes; if (octeon_board_real()) { - printf("octeon_dram == %jx\n", (intmax_t)octeon_dram); - printf("reduced to ram: %u MB", (uint32_t)octeon_dram >> 20); - realmem_bytes = (octeon_dram - PAGE_SIZE); realmem_bytes &= ~(PAGE_SIZE - 1); - printf("Real memory bytes is %x\n", realmem_bytes); } else { /* Simulator we limit to 96 meg */ realmem_bytes = (96 << 20); @@ -678,8 +541,6 @@ octeon_memory_init(void) phys_avail[1] = realmem_bytes; realmem_bytes -= OCTEON_DRAM_FIRST_256_END; realmem_bytes &= ~(PAGE_SIZE - 1); - printf("phys_avail[0] = %#lx phys_avail[1] = %#lx\n", - (long)phys_avail[0], (long)phys_avail[1]); } else { /* Simulator gets 96Meg period. */ phys_avail[1] = (96 << 20); @@ -705,23 +566,14 @@ octeon_memory_init(void) realmem_bytes &= ~(PAGE_SIZE - 1); /* Now map the rest of the memory */ phys_avail[2] = 0x20000000; - printf("realmem_bytes is now at %x\n", realmem_bytes); phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes); - printf("Next block of memory goes from %#lx to %#lx\n", - (long)phys_avail[2], (long)phys_avail[3]); physmem += btoc(phys_avail[3] - phys_avail[2]); - } else { - printf("realmem_bytes is %d\n", realmem_bytes); } realmem = physmem; printf("Total DRAM Size %#X\n", (uint32_t) octeon_dram); printf("Bank 0 = %#08lX -> %#08lX\n", (long)phys_avail[0], (long)phys_avail[1]); printf("Bank 1 = %#08lX -> %#08lX\n", (long)phys_avail[2], (long)phys_avail[3]); - printf("physmem: %#lx\n", physmem); - - Maxmem = physmem; - } void @@ -760,7 +612,15 @@ platform_start(__register_t a0, __regist kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); #endif platform_counter_freq = octeon_get_clock_rate(); - mips_timer_init_params(platform_counter_freq, 1); + mips_timer_init_params(platform_counter_freq, 0); + +#ifdef SMP + /* + * Clear any pending IPIs and enable the IPI interrupt. + */ + oct_write64(OCTEON_CIU_MBOX_CLRX(0), 0xffffffff); + ciu_enable_interrupts(0, CIU_INT_1, CIU_EN_0, OCTEON_CIU_ENABLE_MBOX_INTR, CIU_MIPS_IP3); +#endif } /* impSTART: This stuff should move back into the Cavium SDK */ @@ -982,7 +842,7 @@ octeon_boot_params_init(register_t ptr) printf("Boot Descriptor Ver: %u -> %u/%u", octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100); - printf(" CPU clock: %uMHz\n", octeon_cpu_clock/1000000); + printf(" CPU clock: %uMHz Core Mask: %#x\n", octeon_cpu_clock/1000000, octeon_core_mask); printf(" Dram: %u MB", (uint32_t)(octeon_dram >> 20)); printf(" Board Type: %u Revision: %u/%u\n", octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor); Added: head/sys/mips/cavium/octeon_mp.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/cavium/octeon_mp.c Sat Apr 17 03:08:13 2010 (r206721) @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2004-2010 Juli Mallett + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include + +unsigned octeon_ap_boot = ~0; + +void +platform_ipi_send(int cpuid) +{ + oct_write64(OCTEON_CIU_MBOX_SETX(cpuid), 1); + mips_wbflush(); +} + +void +platform_ipi_clear(void) +{ + uint64_t action; + + action = oct_read64(OCTEON_CIU_MBOX_CLRX(PCPU_GET(cpuid))); + KASSERT(action == 1, ("unexpected IPIs: %#jx", (uintmax_t)action)); + oct_write64(OCTEON_CIU_MBOX_CLRX(PCPU_GET(cpuid)), action); +} + +int +platform_ipi_intrnum(void) +{ + return (1); +} + +void +platform_init_ap(int cpuid) +{ + /* + * Set the exception base. + */ + mips_wr_prid1(0x80000000 | cpuid); + + /* + * Set up interrupts, clear IPIs and unmask the IPI interrupt. + */ + octeon_ciu_reset(); + + oct_write64(OCTEON_CIU_MBOX_CLRX(cpuid), 0xffffffff); + ciu_enable_interrupts(cpuid, CIU_INT_1, CIU_EN_0, OCTEON_CIU_ENABLE_MBOX_INTR, CIU_MIPS_IP3); + + mips_wbflush(); +} + +int +platform_num_processors(void) +{ + return (fls(octeon_core_mask)); +} + +int +platform_start_ap(int cpuid) +{ + if (atomic_cmpset_32(&octeon_ap_boot, ~0, cpuid) == 0) + return (-1); + for (;;) { + DELAY(1000); + if (atomic_cmpset_32(&octeon_ap_boot, 0, ~0) != 0) + return (0); + printf("Waiting for cpu%d to start\n", cpuid); + } +} Modified: head/sys/mips/cavium/octeon_pcmap_regs.h ============================================================================== --- head/sys/mips/cavium/octeon_pcmap_regs.h Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/cavium/octeon_pcmap_regs.h Sat Apr 17 03:08:13 2010 (r206721) @@ -54,14 +54,6 @@ #ifndef LOCORE -/* XXXimp: From Cavium's include/pcpu.h, need to port that over */ -#ifndef OCTEON_SMP -#define OCTEON_CORE_ID 0 -#else -extern struct pcpu *cpuid_to_pcpu[]; -#define OCTEON_CORE_ID (mips_rd_coreid()) -#endif - /* * Utility inlines & macros */ @@ -324,62 +316,6 @@ static inline void oct_write32 (uint64_t #define OCTEON_SCRATCH_2 32 -static inline uint64_t oct_mf_chord (void) -{ - uint64_t dest; - - __asm __volatile ( ".set push\n" - ".set noreorder\n" - ".set noat\n" - ".set mips64\n" - "dmfc2 $1, 0x400\n" - "move %0, $1\n" - ".set pop\n" - : "=r" (dest) : : "$1"); - return dest; -} - - -#define MIPS64_DMFCz(cop,regnum,cp0reg,select) \ - .word (0x40200000 | (cop << 25) | (regnum << 16) | (cp0reg << 11) | select) - - -#define mips64_getcpz_xstr(s) mips64_getcpz_str(s) -#define mips64_getcpz_str(s) #s - -#define mips64_dgetcpz(cop,cpzreg,sel,val_ptr) \ - ({ __asm __volatile( \ - ".set push\n" \ - ".set mips3\n" \ - ".set noreorder\n" \ - ".set noat\n" \ - mips64_getcpz_xstr(MIPS64_DMFCz(cop,1,cpzreg,sel)) "\n" \ - "nop\n" \ - "nop\n" \ - "nop\n" \ - "nop\n" \ - "sd $1,0(%0)\n" \ - ".set pop" \ - : /* no outputs */ : "r" (val_ptr) : "$1"); \ - }) - - -#define mips64_dgetcp2(cp2reg,sel,retval_ptr) \ - mips64_dgetcpz(2,cp2reg,sel,retval_ptr) - - -#define OCTEON_MF_CHORD(dest) mips64_dgetcp2(0x400, 0, &dest) - - - -#define OCTEON_RDHWR(result, regstr) \ - __asm __volatile ( \ - ".set mips3\n" \ - "rdhwr %0,$" OCTEON_TMP_STR(regstr) "\n" \ - ".set mips\n" \ - : "=d" (result)); - -#define CVMX_MF_CHORD(dest) OCTEON_RDHWR(dest, 30) #define OCTEON_CHORD_HEX(dest_ptr) \ ({ __asm __volatile( \ @@ -397,15 +333,6 @@ static inline uint64_t oct_mf_chord (voi : /* no outputs */ : "r" (dest_ptr) : "$2"); \ }) - - -#define OCTEON_MF_CHORD_BAD(dest) \ - __asm __volatile ( \ - ".set mips3\n" \ - "dmfc2 %0, 0x400\n" \ - ".set mips0\n" \ - : "=&r" (dest) : ) - static inline uint64_t oct_scratch_read64 (uint64_t address) { return(*((volatile uint64_t *)(OCTEON_SCRATCH_BASE + address))); @@ -417,17 +344,6 @@ static inline void oct_scratch_write64 ( } -#define OCTEON_READ_CSR32(addr, val) \ - addr_ptr = addr; \ - oct_read_32_ptr(&addr_ptr, &val); - -#define OCTEON_WRITE_CSR32(addr, val, val_dummy) \ - addr_ptr = addr; \ - oct_write_32_ptr(&addr_ptr, &val); \ - oct_read64(OCTEON_MIO_BOOT_BIST_STAT); - - - /* * Octeon Address Space Definitions */ @@ -791,12 +707,6 @@ extern void octeon_led_write_hexchar(int extern void octeon_led_write_hex(uint32_t wl); extern void octeon_led_write_string(const char *str); extern void octeon_reset(void); -extern void octeon_uart_write_byte(int uart_index, uint8_t ch); -extern void octeon_uart_write_string(int uart_index, const char *str); -extern void octeon_uart_write_hex(uint32_t wl); -extern void octeon_uart_write_hex2(uint32_t wl, uint32_t wh); -extern void octeon_wait_uart_flush(int uart_index, uint8_t ch); -extern void octeon_uart_write_byte0(uint8_t ch); extern void octeon_led_write_char0(char val); extern void octeon_led_run_wheel(int *pos, int led_position); extern void octeon_debug_symbol(void); Modified: head/sys/mips/mips/locore.S ============================================================================== --- head/sys/mips/mips/locore.S Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/mips/locore.S Sat Apr 17 03:08:13 2010 (r206721) @@ -162,6 +162,18 @@ VECTOR(_locore, unknown) sw a2, _C_LABEL(fenvp) #endif +#if defined(TARGET_OCTEON) && defined(SMP) + .set push + .set mips32r2 + rdhwr t2, $0 + beqz t2, 1f + nop + j octeon_ap_wait + nop + .set pop +1: +#endif + /* * Initialize stack and call machine startup. */ @@ -178,10 +190,10 @@ VECTOR(_locore, unknown) nop PTR_LA sp, _C_LABEL(thread0) - lw a0, TD_PCB(sp) - li t0, ~7 + PTR_L a0, TD_PCB(sp) + REG_LI t0, ~7 and a0, a0, t0 - subu sp, a0, CALLFRAME_SIZ + PTR_SUBU sp, a0, CALLFRAME_SIZ jal _C_LABEL(mi_startup) # mi_startup(frame) sw zero, CALLFRAME_SIZ - 8(sp) # Zero out old fp for debugger Modified: head/sys/mips/mips/mp_machdep.c ============================================================================== --- head/sys/mips/mips/mp_machdep.c Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/mips/mp_machdep.c Sat Apr 17 03:08:13 2010 (r206721) @@ -157,6 +157,8 @@ start_ap(int cpuid) cpus = mp_naps; dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE); + mips_sync(); + if (platform_start_ap(cpuid) != 0) return (-1); /* could not start AP */ @@ -246,6 +248,8 @@ smp_init_secondary(u_int32_t cpuid) mips_dcache_wbinv_all(); mips_icache_sync_all(); + mips_sync(); + MachSetPID(0); pcpu_init(PCPU_ADDR(cpuid), cpuid, sizeof(struct pcpu)); Modified: head/sys/mips/mips/mpboot.S ============================================================================== --- head/sys/mips/mips/mpboot.S Sat Apr 17 02:28:28 2010 (r206720) +++ head/sys/mips/mips/mpboot.S Sat Apr 17 03:08:13 2010 (r206721) @@ -36,8 +36,21 @@ .set noat .set noreorder +#ifdef TARGET_OCTEON +#define CLEAR_STATUS \ + 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 | SR_KSU_USER | MIPS_SR_BEV) ; \ + and a0, a0, a2 ; \ + mtc0 a0, COP_0_STATUS_REG +#else +#define CLEAR_STATUS \ + mtc0 zero, COP_0_STATUS_REG +#endif + GLOBAL(mpentry) - mtc0 zero, COP_0_STATUS_REG /* disable interrupts */ + CLEAR_STATUS /* disable interrupts */ mtc0 zero, COP_0_CAUSE_REG /* clear soft interrupts */