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} |
|