1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-16 10:20:30 +00:00

Merge pc98's machdep.c into i386/i386/machdep.c.

This commit is contained in:
Yoshihiro Takahashi 2014-10-04 06:01:30 +00:00
parent 986eedef26
commit 9407825cc6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=272492
3 changed files with 309 additions and 3004 deletions

View File

@ -149,6 +149,7 @@ i386/i386/initcpu.c standard
i386/i386/io.c optional io
i386/i386/k6_mem.c optional mem
i386/i386/locore.s standard no-obj
i386/i386/machdep.c standard
i386/i386/mem.c optional mem
i386/i386/minidump_machdep.c standard
i386/i386/mp_clock.c optional smp
@ -237,7 +238,6 @@ pc98/pc98/busiosubr.c standard
pc98/pc98/canbepm.c optional canbepm
pc98/pc98/canbus.c optional canbus
pc98/pc98/canbus_if.m optional canbus
pc98/pc98/machdep.c standard
pc98/pc98/pc98_machdep.c standard
#
# x86 shared code between IA32, AMD64 and PC98 architectures

View File

@ -109,7 +109,11 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_sym.h>
#endif
#ifdef PC98
#include <pc98/pc98/pc98_machdep.h>
#else
#include <isa/rtc.h>
#endif
#include <net/netisr.h>
@ -204,6 +208,14 @@ SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
int _udatasel, _ucodesel;
u_int basemem;
#ifdef PC98
int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */
int need_post_dma_flush; /* If 1, use invd after DMA transfer. */
static int ispc98 = 1;
SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, "");
#endif
int cold = 1;
#ifdef COMPAT_43
@ -259,7 +271,8 @@ cpu_startup(dummy)
{
uintmax_t memsize;
char *sysenv;
#ifndef PC98
/*
* On MacBooks, we need to disallow the legacy USB circuit to
* generate an SMI# because this can cause several problems,
@ -285,6 +298,7 @@ cpu_startup(dummy)
}
freeenv(sysenv);
}
#endif /* !PC98 */
/*
* Good {morning,afternoon,evening,night}.
@ -1235,6 +1249,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RWTUN, &idle_mwait,
#define STATE_MWAIT 0x1
#define STATE_SLEEPING 0x2
#ifndef PC98
static void
cpu_idle_acpi(sbintime_t sbt)
{
@ -1253,6 +1268,7 @@ cpu_idle_acpi(sbintime_t sbt)
__asm __volatile("sti; hlt");
*state = STATE_RUNNING;
}
#endif /* !PC98 */
#ifndef XEN
static void
@ -1370,7 +1386,7 @@ cpu_probe_amdc1e(void)
}
}
#ifdef XEN
#if defined(PC98) || defined(XEN)
void (*cpu_idle_fn)(sbintime_t) = cpu_idle_hlt;
#else
void (*cpu_idle_fn)(sbintime_t) = cpu_idle_acpi;
@ -1458,7 +1474,9 @@ struct {
{ cpu_idle_spin, "spin" },
{ cpu_idle_mwait, "mwait" },
{ cpu_idle_hlt, "hlt" },
#ifndef PC98
{ cpu_idle_acpi, "acpi" },
#endif
{ NULL, NULL }
};
@ -1475,9 +1493,11 @@ idle_sysctl_available(SYSCTL_HANDLER_ARGS)
if (strstr(idle_tbl[i].id_name, "mwait") &&
(cpu_feature2 & CPUID2_MON) == 0)
continue;
#ifndef PC98
if (strcmp(idle_tbl[i].id_name, "acpi") == 0 &&
cpu_idle_hook == NULL)
continue;
#endif
p += sprintf(p, "%s%s", p != avail ? ", " : "",
idle_tbl[i].id_name);
}
@ -1512,9 +1532,11 @@ idle_sysctl(SYSCTL_HANDLER_ARGS)
if (strstr(idle_tbl[i].id_name, "mwait") &&
(cpu_feature2 & CPUID2_MON) == 0)
continue;
#ifndef PC98
if (strcmp(idle_tbl[i].id_name, "acpi") == 0 &&
cpu_idle_hook == NULL)
continue;
#endif
if (strcmp(idle_tbl[i].id_name, buf))
continue;
cpu_idle_fn = idle_tbl[i].id_fn;
@ -2000,7 +2022,7 @@ sdtossd(sd, ssd)
ssd->ssd_gran = sd->sd_gran;
}
#ifndef XEN
#if !defined(PC98) && !defined(XEN)
static int
add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
int *physmap_idxp)
@ -2107,7 +2129,9 @@ add_smap_entries(struct bios_smap *smapbase, vm_paddr_t *physmap,
if (!add_smap_entry(smap, physmap, physmap_idxp))
break;
}
#endif /* !PC98 && !XEN */
#ifndef XEN
static void
basemem_setup(void)
{
@ -2155,7 +2179,7 @@ basemem_setup(void)
for (i = basemem / 4; i < 160; i++)
pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U;
}
#endif
#endif /* !XEN */
/*
* Populate the (physmap) array with base/bound pairs describing the
@ -2170,6 +2194,271 @@ basemem_setup(void)
*
* XXX first should be vm_paddr_t.
*/
#ifdef PC98
static void
getmemsize(int first)
{
int off, physmap_idx, pa_indx, da_indx;
u_long physmem_tunable, memtest;
vm_paddr_t physmap[PHYSMAP_SIZE];
pt_entry_t *pte;
quad_t dcons_addr, dcons_size;
int i;
int pg_n;
u_int extmem;
u_int under16;
vm_paddr_t pa;
bzero(physmap, sizeof(physmap));
/* XXX - some of EPSON machines can't use PG_N */
pg_n = PG_N;
if (pc98_machine_type & M_EPSON_PC98) {
switch (epson_machine_id) {
#ifdef WB_CACHE
default:
#endif
case EPSON_PC486_HX:
case EPSON_PC486_HG:
case EPSON_PC486_HA:
pg_n = 0;
break;
}
}
under16 = pc98_getmemsize(&basemem, &extmem);
basemem_setup();
physmap[0] = 0;
physmap[1] = basemem * 1024;
physmap_idx = 2;
physmap[physmap_idx] = 0x100000;
physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024;
/*
* Now, physmap contains a map of physical memory.
*/
#ifdef SMP
/* make hole for AP bootstrap code */
physmap[1] = mp_bootaddress(physmap[1]);
#endif
/*
* Maxmem isn't the "maximum memory", it's one larger than the
* highest page of the physical address space. It should be
* called something like "Maxphyspage". We may adjust this
* based on ``hw.physmem'' and the results of the memory test.
*/
Maxmem = atop(physmap[physmap_idx + 1]);
#ifdef MAXMEM
Maxmem = MAXMEM / 4;
#endif
if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable))
Maxmem = atop(physmem_tunable);
/*
* By default keep the memtest enabled. Use a general name so that
* one could eventually do more with the code than just disable it.
*/
memtest = 1;
TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest);
if (atop(physmap[physmap_idx + 1]) != Maxmem &&
(boothowto & RB_VERBOSE))
printf("Physical memory use set to %ldK\n", Maxmem * 4);
/*
* If Maxmem has been increased beyond what the system has detected,
* extend the last memory segment to the new limit.
*/
if (atop(physmap[physmap_idx + 1]) < Maxmem)
physmap[physmap_idx + 1] = ptoa((vm_paddr_t)Maxmem);
/*
* We need to divide chunk if Maxmem is larger than 16MB and
* under 16MB area is not full of memory.
* (1) system area (15-16MB region) is cut off
* (2) extended memory is only over 16MB area (ex. Melco "HYPERMEMORY")
*/
if ((under16 != 16 * 1024) && (extmem > 15 * 1024)) {
/* 15M - 16M region is cut off, so need to divide chunk */
physmap[physmap_idx + 1] = under16 * 1024;
physmap_idx += 2;
physmap[physmap_idx] = 0x1000000;
physmap[physmap_idx + 1] = physmap[2] + extmem * 1024;
}
/* call pmap initialization to make new kernel address space */
pmap_bootstrap(first);
/*
* Size up each available chunk of physical memory.
*/
physmap[0] = PAGE_SIZE; /* mask off page 0 */
pa_indx = 0;
da_indx = 1;
phys_avail[pa_indx++] = physmap[0];
phys_avail[pa_indx] = physmap[0];
dump_avail[da_indx] = physmap[0];
pte = CMAP3;
/*
* Get dcons buffer address
*/
if (getenv_quad("dcons.addr", &dcons_addr) == 0 ||
getenv_quad("dcons.size", &dcons_size) == 0)
dcons_addr = 0;
/*
* physmap is in bytes, so when converting to page boundaries,
* round up the start address and round down the end address.
*/
for (i = 0; i <= physmap_idx; i += 2) {
vm_paddr_t end;
end = ptoa((vm_paddr_t)Maxmem);
if (physmap[i + 1] < end)
end = trunc_page(physmap[i + 1]);
for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) {
int tmp, page_bad, full;
int *ptr = (int *)CADDR3;
full = FALSE;
/*
* block out kernel memory as not available.
*/
if (pa >= KERNLOAD && pa < first)
goto do_dump_avail;
/*
* block out dcons buffer
*/
if (dcons_addr > 0
&& pa >= trunc_page(dcons_addr)
&& pa < dcons_addr + dcons_size)
goto do_dump_avail;
page_bad = FALSE;
if (memtest == 0)
goto skip_memtest;
/*
* map page into kernel: valid, read/write,non-cacheable
*/
*pte = pa | PG_V | PG_RW | pg_n;
invltlb();
tmp = *(int *)ptr;
/*
* Test for alternating 1's and 0's
*/
*(volatile int *)ptr = 0xaaaaaaaa;
if (*(volatile int *)ptr != 0xaaaaaaaa)
page_bad = TRUE;
/*
* Test for alternating 0's and 1's
*/
*(volatile int *)ptr = 0x55555555;
if (*(volatile int *)ptr != 0x55555555)
page_bad = TRUE;
/*
* Test for all 1's
*/
*(volatile int *)ptr = 0xffffffff;
if (*(volatile int *)ptr != 0xffffffff)
page_bad = TRUE;
/*
* Test for all 0's
*/
*(volatile int *)ptr = 0x0;
if (*(volatile int *)ptr != 0x0)
page_bad = TRUE;
/*
* Restore original value.
*/
*(int *)ptr = tmp;
skip_memtest:
/*
* Adjust array of valid/good pages.
*/
if (page_bad == TRUE)
continue;
/*
* If this good page is a continuation of the
* previous set of good pages, then just increase
* the end pointer. Otherwise start a new chunk.
* Note that "end" points one higher than end,
* making the range >= start and < end.
* If we're also doing a speculative memory
* test and we at or past the end, bump up Maxmem
* so that we keep going. The first bad page
* will terminate the loop.
*/
if (phys_avail[pa_indx] == pa) {
phys_avail[pa_indx] += PAGE_SIZE;
} else {
pa_indx++;
if (pa_indx == PHYS_AVAIL_ARRAY_END) {
printf(
"Too many holes in the physical address space, giving up\n");
pa_indx--;
full = TRUE;
goto do_dump_avail;
}
phys_avail[pa_indx++] = pa; /* start */
phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */
}
physmem++;
do_dump_avail:
if (dump_avail[da_indx] == pa) {
dump_avail[da_indx] += PAGE_SIZE;
} else {
da_indx++;
if (da_indx == DUMP_AVAIL_ARRAY_END) {
da_indx--;
goto do_next;
}
dump_avail[da_indx++] = pa; /* start */
dump_avail[da_indx] = pa + PAGE_SIZE; /* end */
}
do_next:
if (full)
break;
}
}
*pte = 0;
invltlb();
/*
* XXX
* The last chunk must contain at least one page plus the message
* buffer to avoid complicating other code (message buffer address
* calculation, etc.).
*/
while (phys_avail[pa_indx - 1] + PAGE_SIZE +
round_page(msgbufsize) >= phys_avail[pa_indx]) {
physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
phys_avail[pa_indx--] = 0;
phys_avail[pa_indx--] = 0;
}
Maxmem = atop(phys_avail[pa_indx]);
/* Trim off space for the message buffer. */
phys_avail[pa_indx] -= round_page(msgbufsize);
/* Map the message buffer. */
for (off = 0; off < round_page(msgbufsize); off += PAGE_SIZE)
pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] +
off);
PT_UPDATES_FLUSH();
}
#else /* PC98 */
static void
getmemsize(int first)
{
@ -2567,6 +2856,7 @@ getmemsize(int first)
PT_UPDATES_FLUSH();
}
#endif /* PC98 */
#ifdef XEN
#define MTOPSIZE (1<<(14 + PAGE_SHIFT))
@ -2830,6 +3120,13 @@ init386(first)
*/
proc_linkup0(&proc0, &thread0);
#ifdef PC98
/*
* Initialize DMAC
*/
pc98_init_dmac();
#endif
metadata_missing = 0;
if (bootinfo.bi_modulep) {
preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE;
@ -2993,7 +3290,9 @@ init386(first)
#ifdef DEV_ISA
#ifdef DEV_ATPIC
#ifndef PC98
elcr_probe();
#endif
atpic_startup();
#else
/* Reset and mask the atpics and leave them shut down. */
@ -3027,6 +3326,9 @@ init386(first)
setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
#ifdef PC98
initializecpucache();
#endif
/* make an initial tss so cpu can get interrupt stack on syscall! */
/* Note: -16 is so we can grow the trapframe if we came from vm86 */
@ -3114,6 +3416,7 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
pcpu->pc_acpi_id = 0xffffffff;
}
#ifndef PC98
static int
smap_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
@ -3149,6 +3452,7 @@ smap_sysctl_handler(SYSCTL_HANDLER_ARGS)
}
SYSCTL_PROC(_machdep, OID_AUTO, smap, CTLTYPE_OPAQUE|CTLFLAG_RD, NULL, 0,
smap_sysctl_handler, "S,bios_smap_xattr", "Raw BIOS SMAP data");
#endif /* !PC98 */
void
spinlock_enter(void)

File diff suppressed because it is too large Load Diff