subr_smp.c (2a2968a896765bad1e42703621f348d6357afce9) subr_smp.c (9a3b3e8bce8e8c8bbec663229e16bebb3cfc5d53)
1/*
2 * Copyright (c) 1996, by Steve Passe
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 8 unchanged lines hidden (view full) ---

17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
1/*
2 * Copyright (c) 1996, by Steve Passe
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 8 unchanged lines hidden (view full) ---

17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $Id: mp_machdep.c,v 1.44 1997/08/24 20:33:32 fsmp Exp $
25 * $Id: mp_machdep.c,v 1.45 1997/08/25 21:28:08 bde Exp $
26 */
27
28#include "opt_smp.h"
29
30#include <sys/param.h>
31#include <sys/systm.h>
26 */
27
28#include "opt_smp.h"
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/proc.h>
34#include <sys/sysctl.h>
32
35
33#include <vm/vm.h> /* for KERNBASE */
34#include <vm/vm_param.h> /* for KERNBASE */
35#include <vm/pmap.h> /* for KERNBASE */
36#include <vm/vm.h>
37#include <vm/vm_param.h>
38#include <vm/pmap.h>
36#include <vm/vm_kern.h>
37#include <vm/vm_extern.h>
38
39#include <machine/smp.h>
40#include <machine/apic.h>
41#include <machine/mpapic.h>
42#include <machine/segments.h>
43#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_TEST1 */

--- 181 unchanged lines hidden (view full) ---

225 */
226int cpu_num_to_apic_id[NAPICID];
227int io_num_to_apic_id[NAPICID];
228int apic_id_to_logical[NAPICID];
229
230/* Bitmap of all available CPUs */
231u_int all_cpus;
232
39#include <vm/vm_kern.h>
40#include <vm/vm_extern.h>
41
42#include <machine/smp.h>
43#include <machine/apic.h>
44#include <machine/mpapic.h>
45#include <machine/segments.h>
46#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_TEST1 */

--- 181 unchanged lines hidden (view full) ---

228 */
229int cpu_num_to_apic_id[NAPICID];
230int io_num_to_apic_id[NAPICID];
231int apic_id_to_logical[NAPICID];
232
233/* Bitmap of all available CPUs */
234u_int all_cpus;
235
233/* Boot of AP uses this PTD */
234u_int *bootPTD;
236/* AP uses this PTD during bootstrap */
237pd_entry_t *bootPTD;
235
236/* Hotwire a 0->4MB V==P mapping */
238
239/* Hotwire a 0->4MB V==P mapping */
237extern pt_entry_t KPTphys;
240extern pt_entry_t *KPTphys;
238
239/* Virtual address of per-cpu common_tss */
240extern struct i386tss common_tss;
241
241
242/* Virtual address of per-cpu common_tss */
243extern struct i386tss common_tss;
244
245/* IdlePTD per cpu */
246pd_entry_t *IdlePTDS[NCPU];
247
248/* "my" private page table page, for BSP init */
249extern pt_entry_t SMP_prvpt[];
250
251/* Private page pointer to curcpu's PTD, used during BSP init */
252extern pd_entry_t *my_idlePTD;
253
242/*
243 * Local data and functions.
244 */
245
246static int mp_capable;
247static u_int boot_address;
248static u_int base_memory;
249

--- 1218 unchanged lines hidden (view full) ---

1468 * start each AP in our list
1469 */
1470static int
1471start_all_aps(u_int boot_addr)
1472{
1473 int x, i;
1474 u_char mpbiosreason;
1475 u_long mpbioswarmvec;
254/*
255 * Local data and functions.
256 */
257
258static int mp_capable;
259static u_int boot_address;
260static u_int base_memory;
261

--- 1218 unchanged lines hidden (view full) ---

1480 * start each AP in our list
1481 */
1482static int
1483start_all_aps(u_int boot_addr)
1484{
1485 int x, i;
1486 u_char mpbiosreason;
1487 u_long mpbioswarmvec;
1476 pd_entry_t newptd;
1477 pt_entry_t newpt;
1478 int *newpp;
1488 pd_entry_t *newptd;
1489 pt_entry_t *newpt;
1490 int *newpp, *stack;
1479
1480 POSTCODE(START_ALL_APS_POST);
1481
1482 /* initialize BSP's local APIC */
1483 apic_initialize();
1484 bsp_apic_ready = 1;
1485
1486 /* install the AP 1st level boot code */

--- 6 unchanged lines hidden (view full) ---

1493 mpbiosreason = inb(CMOS_DATA);
1494
1495 /* record BSP in CPU map */
1496 all_cpus = 1;
1497
1498 /* start each AP */
1499 for (x = 1; x <= mp_naps; ++x) {
1500
1491
1492 POSTCODE(START_ALL_APS_POST);
1493
1494 /* initialize BSP's local APIC */
1495 apic_initialize();
1496 bsp_apic_ready = 1;
1497
1498 /* install the AP 1st level boot code */

--- 6 unchanged lines hidden (view full) ---

1505 mpbiosreason = inb(CMOS_DATA);
1506
1507 /* record BSP in CPU map */
1508 all_cpus = 1;
1509
1510 /* start each AP */
1511 for (x = 1; x <= mp_naps; ++x) {
1512
1501 /* HACK HACK HACK !!! */
1513 /* This is a bit verbose, it will go away soon. */
1502
1503 /* alloc new page table directory */
1514
1515 /* alloc new page table directory */
1504 newptd = (pd_entry_t)(kmem_alloc(kernel_map, PAGE_SIZE));
1516 newptd = (pd_entry_t *)(kmem_alloc(kernel_map, PAGE_SIZE));
1505
1517
1518 /* Store the virtual PTD address for this CPU */
1519 IdlePTDS[x] = newptd;
1520
1506 /* clone currently active one (ie: IdlePTD) */
1507 bcopy(PTD, newptd, PAGE_SIZE); /* inc prv page pde */
1508
1509 /* set up 0 -> 4MB P==V mapping for AP boot */
1521 /* clone currently active one (ie: IdlePTD) */
1522 bcopy(PTD, newptd, PAGE_SIZE); /* inc prv page pde */
1523
1524 /* set up 0 -> 4MB P==V mapping for AP boot */
1510 newptd[0] = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
1525 newptd[0] = (pd_entry_t) (PG_V | PG_RW |
1526 ((u_long)KPTphys & PG_FRAME));
1511
1527
1512 /* store PTD for this AP */
1513 bootPTD = (pd_entry_t)vtophys(newptd);
1528 /* store PTD for this AP's boot sequence */
1529 bootPTD = (pd_entry_t *)vtophys(newptd);
1514
1515 /* alloc new page table page */
1530
1531 /* alloc new page table page */
1516 newpt = (pt_entry_t)(kmem_alloc(kernel_map, PAGE_SIZE));
1532 newpt = (pt_entry_t *)(kmem_alloc(kernel_map, PAGE_SIZE));
1517
1518 /* set the new PTD's private page to point there */
1533
1534 /* set the new PTD's private page to point there */
1519 newptd[MPPTDI] = PG_V | PG_RW | vtophys(newpt);
1535 newptd[MPPTDI] = (pt_entry_t)(PG_V | PG_RW | vtophys(newpt));
1520
1521 /* install self referential entry */
1536
1537 /* install self referential entry */
1522 newptd[PTDPTDI] = PG_V | PG_RW | vtophys(newptd);
1538 newptd[PTDPTDI] = (pd_entry_t)(PG_V | PG_RW | vtophys(newptd));
1523
1539
1524 /* get a new private data page */
1540 /* allocate a new private data page */
1525 newpp = (int *)kmem_alloc(kernel_map, PAGE_SIZE);
1526
1527 /* wire it into the private page table page */
1541 newpp = (int *)kmem_alloc(kernel_map, PAGE_SIZE);
1542
1543 /* wire it into the private page table page */
1528 newpt[0] = PG_V | PG_RW | vtophys(newpp);
1544 newpt[0] = (pt_entry_t)(PG_V | PG_RW | vtophys(newpp));
1529
1530 /* wire the ptp into itself for access */
1545
1546 /* wire the ptp into itself for access */
1531 newpt[1] = PG_V | PG_RW | vtophys(newpt);
1547 newpt[1] = (pt_entry_t)(PG_V | PG_RW | vtophys(newpt));
1532
1548
1533 /* and the local apic */
1549 /* copy in the pointer to the local apic */
1534 newpt[2] = SMP_prvpt[2];
1535
1536 /* and the IO apic mapping[s] */
1537 for (i = 16; i < 32; i++)
1538 newpt[i] = SMP_prvpt[i];
1539
1550 newpt[2] = SMP_prvpt[2];
1551
1552 /* and the IO apic mapping[s] */
1553 for (i = 16; i < 32; i++)
1554 newpt[i] = SMP_prvpt[i];
1555
1540 /* prime data page for it to use */
1541 newpp[0] = x; /* cpuid */
1542 newpp[1] = 0; /* curproc */
1543 newpp[2] = 0; /* curpcb */
1544 newpp[3] = 0; /* npxproc */
1545 newpp[4] = 0; /* runtime.tv_sec */
1546 newpp[5] = 0; /* runtime.tv_usec */
1547 newpp[6] = x << 24; /* cpu_lockid */
1556 /* allocate and set up an idle stack data page */
1557 stack = (int *)kmem_alloc(kernel_map, PAGE_SIZE);
1558 newpt[3] = (pt_entry_t)(PG_V | PG_RW | vtophys(stack));
1548
1559
1549 /* XXX NOTE: ABANDON bootPTD for now!!!! */
1560 newpt[4] = 0; /* *prv_CMAP1 */
1561 newpt[5] = 0; /* *prv_CMAP2 */
1562 newpt[6] = 0; /* *prv_CMAP3 */
1550
1563
1551 /* END REVOLTING HACKERY */
1564 /* prime data page for it to use */
1565 newpp[0] = x; /* cpuid */
1566 newpp[1] = 0; /* curproc */
1567 newpp[2] = 0; /* curpcb */
1568 newpp[3] = 0; /* npxproc */
1569 newpp[4] = 0; /* runtime.tv_sec */
1570 newpp[5] = 0; /* runtime.tv_usec */
1571 newpp[6] = x << 24; /* cpu_lockid */
1572 newpp[7] = 0; /* other_cpus */
1573 newpp[8] = (int)bootPTD; /* my_idlePTD */
1574 newpp[9] = 0; /* ss_tpr */
1575 newpp[10] = (int)&newpt[4]; /* prv_CMAP1 */
1576 newpp[11] = (int)&newpt[5]; /* prv_CMAP2 */
1577 newpp[12] = (int)&newpt[6]; /* prv_CMAP3 */
1552
1553 /* setup a vector to our boot code */
1554 *((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET;
1555 *((volatile u_short *) WARMBOOT_SEG) = (boot_addr >> 4);
1556 outb(CMOS_REG, BIOS_RESET);
1557 outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */
1558
1559 /* attempt to start the Application Processor */

--- 20 unchanged lines hidden (view full) ---

1580 /* fill in our (BSP) APIC version */
1581 cpu_apic_versions[0] = lapic.version;
1582
1583 /* restore the warmstart vector */
1584 *(u_long *) WARMBOOT_OFF = mpbioswarmvec;
1585 outb(CMOS_REG, BIOS_RESET);
1586 outb(CMOS_DATA, mpbiosreason);
1587
1578
1579 /* setup a vector to our boot code */
1580 *((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET;
1581 *((volatile u_short *) WARMBOOT_SEG) = (boot_addr >> 4);
1582 outb(CMOS_REG, BIOS_RESET);
1583 outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */
1584
1585 /* attempt to start the Application Processor */

--- 20 unchanged lines hidden (view full) ---

1606 /* fill in our (BSP) APIC version */
1607 cpu_apic_versions[0] = lapic.version;
1608
1609 /* restore the warmstart vector */
1610 *(u_long *) WARMBOOT_OFF = mpbioswarmvec;
1611 outb(CMOS_REG, BIOS_RESET);
1612 outb(CMOS_DATA, mpbiosreason);
1613
1614 /*
1615 * Set up the idle context for the BSP. Similar to above except
1616 * that some was done by locore, some by pmap.c and some is implicit
1617 * because the BSP is cpu#0 and the page is initially zero, and also
1618 * because we can refer to variables by name on the BSP..
1619 */
1620 newptd = (pd_entry_t *)(kmem_alloc(kernel_map, PAGE_SIZE));
1621
1622 bcopy(PTD, newptd, PAGE_SIZE); /* inc prv page pde */
1623 IdlePTDS[0] = newptd;
1624
1625 /* Point PTD[] to this page instead of IdlePTD's physical page */
1626 newptd[PTDPTDI] = (pd_entry_t)(PG_V | PG_RW | vtophys(newptd));
1627
1628 my_idlePTD = (pd_entry_t *)vtophys(newptd);
1629
1630 /* Allocate and setup BSP idle stack */
1631 stack = (int *)kmem_alloc(kernel_map, PAGE_SIZE);
1632 SMP_prvpt[3] = (pt_entry_t)(PG_V | PG_RW | vtophys(stack));
1633
1588 pmap_set_opt_bsp();
1589
1590 /* number of APs actually started */
1591 return mp_ncpus - 1;
1592}
1593
1594
1595/*

--- 199 unchanged lines hidden (view full) ---

1795 * -1: error
1796 * 0: NA
1797 * 1: ok
1798 *
1799 * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
1800 * from executing at same time.
1801 */
1802int
1634 pmap_set_opt_bsp();
1635
1636 /* number of APs actually started */
1637 return mp_ncpus - 1;
1638}
1639
1640
1641/*

--- 199 unchanged lines hidden (view full) ---

1841 * -1: error
1842 * 0: NA
1843 * 1: ok
1844 *
1845 * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
1846 * from executing at same time.
1847 */
1848int
1803stop_cpus( u_int map )
1849stop_cpus(u_int map)
1804{
1805 if (!smp_active)
1806 return 0;
1807
1808 /* send IPI to all CPUs in map */
1809 stopped_cpus = 0;
1810
1811 /* send the Xcpustop IPI to all CPUs in map */

--- 15 unchanged lines hidden (view full) ---

1827 * - Waits for each to restart.
1828 *
1829 * Returns:
1830 * -1: error
1831 * 0: NA
1832 * 1: ok
1833 */
1834int
1850{
1851 if (!smp_active)
1852 return 0;
1853
1854 /* send IPI to all CPUs in map */
1855 stopped_cpus = 0;
1856
1857 /* send the Xcpustop IPI to all CPUs in map */

--- 15 unchanged lines hidden (view full) ---

1873 * - Waits for each to restart.
1874 *
1875 * Returns:
1876 * -1: error
1877 * 0: NA
1878 * 1: ok
1879 */
1880int
1835restart_cpus( u_int map )
1881restart_cpus(u_int map)
1836{
1837 if (!smp_active)
1838 return 0;
1839
1840 started_cpus = map; /* signal other cpus to restart */
1841
1842 while (started_cpus) /* wait for each to clear its bit */
1843 /* spin */ ;
1844
1845 return 1;
1846}
1882{
1883 if (!smp_active)
1884 return 0;
1885
1886 started_cpus = map; /* signal other cpus to restart */
1887
1888 while (started_cpus) /* wait for each to clear its bit */
1889 /* spin */ ;
1890
1891 return 1;
1892}
1893
1894int smp_active = 0; /* are the APs allowed to run? */
1895SYSCTL_INT(_machdep, OID_AUTO, smp_active, CTLFLAG_RW, &smp_active, 0, "");
1896
1897/* XXX maybe should be hw.ncpu */
1898int smp_cpus = 1; /* how many cpu's running */
1899SYSCTL_INT(_machdep, OID_AUTO, smp_cpus, CTLFLAG_RD, &smp_cpus, 0, "");
1900
1901int invltlb_ok = 0; /* throttle smp_invltlb() till safe */
1902SYSCTL_INT(_machdep, OID_AUTO, invltlb_ok, CTLFLAG_RW, &invltlb_ok, 0, "");
1903
1904int do_page_zero_idle = 0; /* bzero pages for fun and profit in idleloop */
1905SYSCTL_INT(_machdep, OID_AUTO, do_page_zero_idle, CTLFLAG_RW,
1906 &do_page_zero_idle, 0, "");
1907
1908
1909/*
1910 * This is called once the rest of the system is up and running and we're
1911 * ready to let the AP's out of the pen.
1912 */
1913void ap_init(void);
1914
1915void
1916ap_init()
1917{
1918 u_int temp;
1919 u_int apic_id;
1920
1921 smp_cpus++;
1922
1923 /* Build our map of 'other' CPUs. */
1924 other_cpus = all_cpus & ~(1 << cpuid);
1925
1926 printf("SMP: AP CPU #%d Launched!\n", cpuid);
1927
1928 /* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
1929 load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
1930
1931 /* A quick check from sanity claus */
1932 apic_id = (apic_id_to_logical[(lapic.id & 0x0f000000) >> 24]);
1933 if (cpuid != apic_id) {
1934 printf("SMP: cpuid = %d\n", cpuid);
1935 printf("SMP: apic_id = %d\n", apic_id);
1936 printf("PTD[MPPTDI] = %08x\n", PTD[MPPTDI]);
1937 panic("cpuid mismatch! boom!!");
1938 }
1939
1940 /* Init local apic for irq's */
1941 apic_initialize();
1942
1943 /*
1944 * Activate smp_invltlb, although strictly speaking, this isn't
1945 * quite correct yet. We should have a bitfield for cpus willing
1946 * to accept TLB flush IPI's or something and sync them.
1947 */
1948 invltlb_ok = 1;
1949 smp_active = 1; /* historic */
1950
1951 curproc = NULL; /* make sure */
1952}