From d0257d908f9ef46ce46a3d5a91d6c885154fb6df Mon Sep 17 00:00:00 2001 From: Joe Talbott Date: Mon, 18 Jun 2007 18:57:13 +0000 Subject: [PATCH] Make vkernel compile with 'options SMP'. Most functions are stubs that call panic(9). Reviewed-By: Matt Dillon --- sys/kern/kern_shutdown.c | 5 +- sys/platform/vkernel/conf/files | 4 +- sys/platform/vkernel/i386/autoconf.c | 3 +- sys/platform/vkernel/i386/mp.c | 134 +++++++++++++++++ sys/platform/vkernel/i386/mplock.s | 280 +++++++++++++++++++++++++++++++++++ sys/platform/vkernel/i386/trap.c | 8 +- sys/platform/vkernel/include/smp.h | 8 +- sys/platform/vkernel/platform/pmap.c | 12 +- 8 files changed, 439 insertions(+), 15 deletions(-) create mode 100644 sys/platform/vkernel/i386/mp.c create mode 100644 sys/platform/vkernel/i386/mplock.s diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index a725c64e23..92a8e7a8e9 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -37,7 +37,7 @@ * * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94 * $FreeBSD: src/sys/kern/kern_shutdown.c,v 1.72.2.12 2002/02/21 19:15:10 dillon Exp $ - * $DragonFly: src/sys/kern/kern_shutdown.c,v 1.57 2007/06/17 03:51:10 dillon Exp $ + * $DragonFly: src/sys/kern/kern_shutdown.c,v 1.58 2007/06/18 18:57:12 josepht Exp $ */ #include "opt_ddb.h" @@ -782,10 +782,9 @@ panic(const char *fmt, ...) __va_end(ap); kprintf("panic: %s\n", buf); #ifdef SMP - /* three separate prints in case of an unmapped page and trap */ + /* two separate prints in case of an unmapped page and trap */ kprintf("mp_lock = %08x; ", mp_lock); kprintf("cpuid = %d; ", mycpu->gd_cpuid); - kprintf("lapic.id = %08x\n", lapic.id); #endif #if defined(DDB) diff --git a/sys/platform/vkernel/conf/files b/sys/platform/vkernel/conf/files index 84afe3e320..906ff7ac7a 100644 --- a/sys/platform/vkernel/conf/files +++ b/sys/platform/vkernel/conf/files @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $DragonFly: src/sys/platform/vkernel/conf/files,v 1.17 2007/06/17 03:52:03 dillon Exp $ +# $DragonFly: src/sys/platform/vkernel/conf/files,v 1.18 2007/06/18 18:57:12 josepht Exp $ # bf_enc.o optional ipsec ipsec_esp \ dependency "$S/crypto/blowfish/arch/i386/bf_enc.S $S/crypto/blowfish/arch/i386/bf_enc_586.S $S/crypto/blowfish/arch/i386/bf_enc_686.S" \ @@ -31,6 +31,8 @@ vfs/smbfs/smbfs_vnops.c optional smbfs cpu/i386/misc/atomic.c standard \ compile-with "${CC} -c ${CFLAGS} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}" platform/vkernel/i386/autoconf.c standard +platform/vkernel/i386/mp.c optional smp +platform/vkernel/i386/mplock.s optional smp # # DDB XXX cpu/i386/misc/elf_machdep.c standard diff --git a/sys/platform/vkernel/i386/autoconf.c b/sys/platform/vkernel/i386/autoconf.c index 269963990b..427ea10120 100644 --- a/sys/platform/vkernel/i386/autoconf.c +++ b/sys/platform/vkernel/i386/autoconf.c @@ -35,7 +35,7 @@ * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 * $FreeBSD: src/sys/i386/i386/autoconf.c,v 1.146.2.2 2001/06/07 06:05:58 dd Exp $ - * $DragonFly: src/sys/platform/vkernel/i386/autoconf.c,v 1.13 2007/06/17 23:50:16 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/i386/autoconf.c,v 1.14 2007/06/18 18:57:12 josepht Exp $ */ /* @@ -82,6 +82,7 @@ #include #include #endif +#include #include #include diff --git a/sys/platform/vkernel/i386/mp.c b/sys/platform/vkernel/i386/mp.c new file mode 100644 index 0000000000..eadab732a5 --- /dev/null +++ b/sys/platform/vkernel/i386/mp.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2007 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * 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. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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. + * + * $DragonFly: src/sys/platform/vkernel/i386/mp.c,v 1.1 2007/06/18 18:57:12 josepht Exp $ + */ + +#include +#include + +#include +#include + +#if 0 +volatile lapic_t lapic; /* needed for kern/kern_shutdown.c */ +#endif +volatile u_int stopped_cpus; +cpumask_t smp_active_mask = 1; /* which cpus are ready for IPIs etc? */ +#if 0 +u_int mp_lock; +#endif + +void +mp_start(void) +{ + panic("XXX mp_start()"); +} + +void +mp_announce(void) +{ + panic("XXX mp_announce()"); +} + +#if 0 +void +get_mplock(void) +{ + panic("XXX get_mplock()"); +} + +int +try_mplock(void) +{ + panic("XXX try_mplock()"); +} + +void +rel_mplock(void) +{ + panic("XXX rel_mplock()"); +} + +int +cpu_try_mplock(void) +{ + panic("XXX cpu_try_mplock()"); +} +void +cpu_get_initial_mplock(void) +{ + panic("XXX cpu_get_initial_mplock()"); +} +#endif + + +void +forward_fastint_remote(void *arg) +{ + panic("XXX forward_fastint_remote()"); +} + +void +cpu_send_ipiq(int dcpu) +{ + panic("XXX cpu_send_ipiq()"); +} + +void +smp_invltlb(void) +{ +#ifdef SMP + panic("XXX smp_invltlb()"); +#endif +} + +int +stop_cpus(u_int map) +{ + panic("XXX stop_cpus()"); +} + +int +restart_cpus(u_int map) +{ + panic("XXX restart_cpus()"); +} + +void +ap_init(void) +{ + panic("XXX ap_init()"); +} + + diff --git a/sys/platform/vkernel/i386/mplock.s b/sys/platform/vkernel/i386/mplock.s new file mode 100644 index 0000000000..d2ae09c701 --- /dev/null +++ b/sys/platform/vkernel/i386/mplock.s @@ -0,0 +1,280 @@ +/* + * $FreeBSD: src/sys/i386/i386/mplock.s,v 1.29.2.2 2000/05/16 06:58:06 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/i386/mplock.s,v 1.1 2007/06/18 18:57:12 josepht Exp $ + * + * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * 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. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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. + * + * DragonFly MPLOCK operation + * + * Each thread has an MP lock count, td_mpcount, and there is a shared + * global called mp_lock. mp_lock is the physical MP lock and contains either + * -1 or the cpuid of the cpu owning the lock. The count is *NOT* integrated + * into mp_lock but instead resides in each thread td_mpcount. + * + * When obtaining or releasing the MP lock the td_mpcount is PREDISPOSED + * to the desired count *PRIOR* to operating on the mp_lock itself. MP + * lock operations can occur outside a critical section with interrupts + * enabled with the provisio (which the routines below handle) that an + * interrupt may come along and preempt us, racing our cmpxchgl instruction + * to perform the operation we have requested by pre-disposing td_mpcount. + * + * Additionally, the LWKT threading system manages the MP lock and + * lwkt_switch(), in particular, may be called after pre-disposing td_mpcount + * to handle 'blocking' on the MP lock. + * + * + * Recoded from the FreeBSD original: + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +#include +#if 0 +#include +#endif + +#include "assym.s" + +/* + * YYY Debugging only. Define this to be paranoid about invalidating the + * TLB when we get giant. + */ +#undef PARANOID_INVLTLB + + .data + ALIGN_DATA +#ifdef SMP + .globl mp_lock +mp_lock: + .long -1 /* initialized to not held */ +#endif + + .text + SUPERALIGN_TEXT + + /* + * Note on cmpxchgl... exchanges ecx with mem if mem matches eax. + * Z=1 (jz) on success. A lock prefix is required for MP. + */ +NON_GPROF_ENTRY(cpu_get_initial_mplock) + movl PCPU(curthread),%ecx + movl $1,TD_MPCOUNT(%ecx) /* curthread has mpcount of 1 */ + movl $0,mp_lock /* owned by cpu 0 */ + NON_GPROF_RET + + /* + * cpu_try_mplock() returns non-zero on success, 0 on failure. It + * only adjusts mp_lock, it does not touch td_mpcount. Callers + * should always increment td_mpcount *before* trying to acquire + * the actual lock, predisposing td_mpcount to the desired state of + * the lock. + * + * NOTE! Only call cpu_try_mplock() inside a critical section. If + * you don't an interrupt can come along and get and release + * the lock before our cmpxchgl instruction, causing us to fail + * but resulting in the lock being held by our cpu. + */ +NON_GPROF_ENTRY(cpu_try_mplock) + movl PCPU(cpuid),%ecx + movl $-1,%eax + lock cmpxchgl %ecx,mp_lock /* ecx<->mem if eax matches */ + jnz 1f +#ifdef PARANOID_INVLTLB + movl %cr3,%eax; movl %eax,%cr3 /* YYY check and remove */ +#endif + movl $1,%eax + NON_GPROF_RET +1: + subl %eax,%eax + NON_GPROF_RET + + /* + * get_mplock() Obtains the MP lock and may switch away if it cannot + * get it. This routine may be called WITHOUT a critical section + * and with cpu interrupts enabled. + * + * To handle races in a sane fashion we predispose TD_MPCOUNT, + * which prevents us from losing the lock in a race if we already + * have it or happen to get it. It also means that we might get + * the lock in an interrupt race before we have a chance to execute + * our cmpxchgl instruction, so we have to handle that case. + * Fortunately simply calling lwkt_switch() handles the situation + * for us and also 'blocks' us until the MP lock can be obtained. + */ +NON_GPROF_ENTRY(get_mplock) + movl PCPU(cpuid),%ecx + movl PCPU(curthread),%edx + incl TD_MPCOUNT(%edx) /* predispose */ + cmpl %ecx,mp_lock + jne 1f + NON_GPROF_RET /* success! */ + + /* + * We don't already own the mp_lock, use cmpxchgl to try to get + * it. + */ +1: + movl $-1,%eax + lock cmpxchgl %ecx,mp_lock + jnz 2f +#ifdef PARANOID_INVLTLB + movl %cr3,%eax; movl %eax,%cr3 /* YYY check and remove */ +#endif + NON_GPROF_RET /* success */ + + /* + * Failure, but we could end up owning mp_lock anyway due to + * an interrupt race. lwkt_switch() will clean up the mess + * and 'block' until the mp_lock is obtained. + * + * Create a stack frame for the call so KTR logs the stack + * backtrace properly. + */ +2: + pushl %ebp + movl %esp,%ebp + call lwkt_mp_lock_contested + popl %ebp +#ifdef INVARIANTS + movl PCPU(cpuid),%eax /* failure */ + cmpl %eax,mp_lock + jne 4f +#endif + NON_GPROF_RET +#ifdef INVARIANTS +4: + cmpl $0,panicstr /* don't double panic */ + je badmp_get2 + NON_GPROF_RET +#endif + + /* + * try_mplock() attempts to obtain the MP lock. 1 is returned on + * success, 0 on failure. We do not have to be in a critical section + * and interrupts are almost certainly enabled. + * + * We must pre-dispose TD_MPCOUNT in order to deal with races in + * a reasonable way. + * + */ +NON_GPROF_ENTRY(try_mplock) + movl PCPU(cpuid),%ecx + movl PCPU(curthread),%edx + incl TD_MPCOUNT(%edx) /* pre-dispose for race */ + cmpl %ecx,mp_lock + je 1f /* trivial success */ + movl $-1,%eax + lock cmpxchgl %ecx,mp_lock + jnz 2f + /* + * Success + */ +#ifdef PARANOID_INVLTLB + movl %cr3,%eax; movl %eax,%cr3 /* YYY check and remove */ +#endif +1: + movl $1,%eax /* success (cmpxchgl good!) */ + NON_GPROF_RET + + /* + * The cmpxchgl failed but we might have raced. Undo the mess by + * predispoing TD_MPCOUNT and then checking. If TD_MPCOUNT is + * still non-zero we don't care what state the lock is in (since + * we obviously didn't own it above), just return failure even if + * we won the lock in an interrupt race. If TD_MPCOUNT is zero + * make sure we don't own the lock in case we did win it in a race. + */ +2: + decl TD_MPCOUNT(%edx) + cmpl $0,TD_MPCOUNT(%edx) + jne 3f + movl PCPU(cpuid),%eax + movl $-1,%ecx + lock cmpxchgl %ecx,mp_lock +3: + subl %eax,%eax + NON_GPROF_RET + + /* + * rel_mplock() releases a previously obtained MP lock. + * + * In order to release the MP lock we pre-dispose TD_MPCOUNT for + * the release and basically repeat the release portion of try_mplock + * above. + */ +NON_GPROF_ENTRY(rel_mplock) + movl PCPU(curthread),%edx + movl TD_MPCOUNT(%edx),%eax +#ifdef INVARIANTS + cmpl $0,%eax + je badmp_rel +#endif + subl $1,%eax + movl %eax,TD_MPCOUNT(%edx) + cmpl $0,%eax + jne 3f + movl PCPU(cpuid),%eax + movl $-1,%ecx + lock cmpxchgl %ecx,mp_lock +3: + NON_GPROF_RET + +#ifdef INVARIANTS + +badmp_get: + pushl $bmpsw1 + call panic +badmp_get2: + pushl $bmpsw1a + call panic +badmp_rel: + pushl $bmpsw2 + call panic + + .data + +bmpsw1: + .asciz "try/get_mplock(): already have lock! %d %p" + +bmpsw1a: + .asciz "try/get_mplock(): failed on count or switch %d %p" + +bmpsw2: + .asciz "rel_mplock(): mpcount already 0 @ %p %p %p %p %p %p %p %p!" + +#endif + diff --git a/sys/platform/vkernel/i386/trap.c b/sys/platform/vkernel/i386/trap.c index 8714ccd530..b600c5e2c8 100644 --- a/sys/platform/vkernel/i386/trap.c +++ b/sys/platform/vkernel/i386/trap.c @@ -36,7 +36,7 @@ * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 * $FreeBSD: src/sys/i386/i386/trap.c,v 1.147.2.11 2003/02/27 19:09:59 luoqi Exp $ - * $DragonFly: src/sys/platform/vkernel/i386/trap.c,v 1.23 2007/04/29 18:25:38 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/i386/trap.c,v 1.24 2007/06/18 18:57:12 josepht Exp $ */ /* @@ -950,10 +950,9 @@ trap_fatal(struct trapframe *frame, int usermode, vm_offset_t eva) (usermode ? "user" : "kernel")); } #ifdef SMP - /* three separate prints in case of a trap on an unmapped page */ + /* two separate prints in case of a trap on an unmapped page */ kprintf("mp_lock = %08x; ", mp_lock); kprintf("cpuid = %d; ", mycpu->gd_cpuid); - kprintf("lapic.id = %08x\n", lapic.id); #endif if (type == T_PAGEFLT) { kprintf("fault virtual address = 0x%x\n", eva); @@ -1046,10 +1045,9 @@ dblfault_handler(void) kprintf("esp = 0x%x\n", gd->gd_common_tss.tss_esp); kprintf("ebp = 0x%x\n", gd->gd_common_tss.tss_ebp); #ifdef SMP - /* three separate prints in case of a trap on an unmapped page */ + /* two separate prints in case of a trap on an unmapped page */ kprintf("mp_lock = %08x; ", mp_lock); kprintf("cpuid = %d; ", mycpu->gd_cpuid); - kprintf("lapic.id = %08x\n", lapic.id); #endif panic("double fault"); } diff --git a/sys/platform/vkernel/include/smp.h b/sys/platform/vkernel/include/smp.h index a4536a3b24..277cd39394 100644 --- a/sys/platform/vkernel/include/smp.h +++ b/sys/platform/vkernel/include/smp.h @@ -7,7 +7,7 @@ * ---------------------------------------------------------------------------- * * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $ - * $DragonFly: src/sys/platform/vkernel/include/smp.h,v 1.1 2006/11/08 17:40:00 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/include/smp.h,v 1.2 2007/06/18 18:57:13 josepht Exp $ * */ @@ -48,9 +48,9 @@ void bootMP (void); #endif -#if 0 /* global data in apic_vector.s */ extern volatile u_int stopped_cpus; +#if 0 extern volatile u_int started_cpus; extern volatile u_int checkstate_probed_cpus; @@ -97,8 +97,10 @@ extern struct pcb stoppcbs[]; void *permanent_io_mapping(vm_paddr_t); u_int mp_bootaddress (u_int); int mp_probe (void); +#endif void mp_start (void); void mp_announce (void); +#if 0 u_int isa_apic_mask (u_int); int isa_apic_irq (int); int pci_apic_irq (int, int, int); @@ -115,9 +117,11 @@ int apic_polarity (int, int); void assign_apic_irq (int apic, int intpin, int irq); void revoke_apic_irq (int irq); void init_secondary (void); +#endif int stop_cpus (u_int); void ap_init (void); int restart_cpus (u_int); +#if 0 void forward_signal (struct proc *); #endif diff --git a/sys/platform/vkernel/platform/pmap.c b/sys/platform/vkernel/platform/pmap.c index a3b5b1a478..aba704af46 100644 --- a/sys/platform/vkernel/platform/pmap.c +++ b/sys/platform/vkernel/platform/pmap.c @@ -38,7 +38,7 @@ * * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 * $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $ - * $DragonFly: src/sys/platform/vkernel/platform/pmap.c,v 1.21 2007/04/29 18:25:39 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/platform/pmap.c,v 1.22 2007/06/18 18:57:13 josepht Exp $ */ /* * NOTE: PMAP_INVAL_ADD: In pc32 this function is called prior to adjusting @@ -285,8 +285,11 @@ pmap_release(struct pmap *pmap) panic("pmap_release: pteobj reference count != 1"); #endif #ifdef SMP + panic("Must write code to clear PTxpdir cache across all CPUs"); +#if 0 #error "Must write code to clear PTxpdir cache across all CPUs" #endif +#endif /* * Once we destroy the page table, the mapping becomes invalid. * Rather then waste time doing a madvise @@ -534,8 +537,11 @@ inval_ptbase_pagedir(pmap_t pmap, vm_pindex_t pindex) vm_offset_t va; #ifdef SMP + panic("Must inval self-mappings in all gd's"); +#if 0 #error "Must inval self-mappings in all gd's" #endif +#endif if (pmap == &kernel_pmap) { va = (vm_offset_t)KernelPTA + (pindex << PAGE_SHIFT); madvise((void *)va, PAGE_SIZE, MADV_INVAL); @@ -788,7 +794,7 @@ pmap_qenter(vm_offset_t va, struct vm_page **m, int count) va += PAGE_SIZE; } #ifdef SMP - XXX + panic("XXX smp_invltlb()"); smp_invltlb(); #endif } @@ -843,7 +849,7 @@ pmap_qremove(vm_offset_t va, int count) va += PAGE_SIZE; } #ifdef SMP - XXX + panic("XXX smp_invltlb()"); smp_invltlb(); #endif } -- 2.11.4.GIT