From owner-svn-src-all@FreeBSD.ORG Fri Mar 19 21:15:44 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 57F251065672; Fri, 19 Mar 2010 21:15:44 +0000 (UTC) (envelope-from jkim@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3A2FA8FC24; Fri, 19 Mar 2010 21:15:44 +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 o2JLFiLo066836; Fri, 19 Mar 2010 21:15:44 GMT (envelope-from jkim@svn.freebsd.org) Received: (from jkim@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o2JLFirf066834; Fri, 19 Mar 2010 21:15:44 GMT (envelope-from jkim@svn.freebsd.org) Message-Id: <201003192115.o2JLFirf066834@svn.freebsd.org> From: Jung-uk Kim Date: Fri, 19 Mar 2010 21:15:44 +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: r205347 - head/sys/compat/x86bios X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Mar 2010 21:15:44 -0000 Author: jkim Date: Fri Mar 19 21:15:43 2010 New Revision: 205347 URL: http://svn.freebsd.org/changeset/base/205347 Log: - Map EBDA if available and add 64KB above 1MB (high memory), just in case. - Print the initial memory map when bootverbose is set. - Change the page fault address format from linear to %cs:%ip style. - Move duplicate code into a newly added function. - Add strictly aligned memory access for distant future. ;-) Modified: head/sys/compat/x86bios/x86bios.c Modified: head/sys/compat/x86bios/x86bios.c ============================================================================== --- head/sys/compat/x86bios/x86bios.c Fri Mar 19 20:14:27 2010 (r205346) +++ head/sys/compat/x86bios/x86bios.c Fri Mar 19 21:15:43 2010 (r205347) @@ -56,18 +56,20 @@ __FBSDID("$FreeBSD$"); #define X86BIOS_IVT_SIZE 0x00000500 /* 1K + 256 (BDA) */ #define X86BIOS_SEG_SIZE 0x00010000 /* 64K */ -#define X86BIOS_MEM_SIZE 0x00100000 /* 1M */ +#define X86BIOS_MEM_SIZE (0x00100000 + X86BIOS_SEG_SIZE) + /* 1M + 64K (high memory) */ #define X86BIOS_IVT_BASE 0x00000000 #define X86BIOS_RAM_BASE 0x00001000 -#define X86BIOS_ROM_BASE 0x000a0000 /* XXX EBDA? */ +#define X86BIOS_ROM_BASE 0x000a0000 -#define X86BIOS_ROM_SIZE (X86BIOS_MEM_SIZE - X86BIOS_ROM_BASE) +#define X86BIOS_ROM_SIZE (X86BIOS_MEM_SIZE - (uint32_t)x86bios_rom_phys) #define X86BIOS_PAGES (X86BIOS_MEM_SIZE / X86BIOS_PAGE_SIZE) #define X86BIOS_R_DS _pad1 #define X86BIOS_R_SS _pad2 +#define X86BIOS_R_SP _pad3.I16_reg.x_reg static struct x86emu x86bios_emu; @@ -79,11 +81,13 @@ static void *x86bios_seg; static vm_offset_t *x86bios_map; +static vm_paddr_t x86bios_rom_phys; static vm_paddr_t x86bios_seg_phys; static int x86bios_fault; static uint32_t x86bios_fault_addr; -static uint32_t x86bios_fault_inst; +static uint16_t x86bios_fault_cs; +static uint16_t x86bios_fault_ip; SYSCTL_NODE(_debug, OID_AUTO, x86bios, CTLFLAG_RD, NULL, "x86bios debugging"); static int x86bios_trace_call; @@ -101,7 +105,9 @@ x86bios_set_fault(struct x86emu *emu, ui x86bios_fault = 1; x86bios_fault_addr = addr; - x86bios_fault_inst = (emu->x86.R_CS << 4) + emu->x86.R_IP; + x86bios_fault_cs = emu->x86.R_CS; + x86bios_fault_ip = emu->x86.R_IP; + x86emu_halt_sys(emu); } static void * @@ -136,10 +142,8 @@ x86bios_emu_rdb(struct x86emu *emu, uint uint8_t *va; va = x86bios_get_pages(addr, sizeof(*va)); - if (va == NULL) { + if (va == NULL) x86bios_set_fault(emu, addr); - x86emu_halt_sys(emu); - } return (*va); } @@ -150,11 +154,14 @@ x86bios_emu_rdw(struct x86emu *emu, uint uint16_t *va; va = x86bios_get_pages(addr, sizeof(*va)); - if (va == NULL) { + if (va == NULL) x86bios_set_fault(emu, addr); - x86emu_halt_sys(emu); - } +#ifndef __NO_STRICT_ALIGNMENT + if ((addr & 1) != 0) + return (le16dec(va)); + else +#endif return (le16toh(*va)); } @@ -164,11 +171,14 @@ x86bios_emu_rdl(struct x86emu *emu, uint uint32_t *va; va = x86bios_get_pages(addr, sizeof(*va)); - if (va == NULL) { + if (va == NULL) x86bios_set_fault(emu, addr); - x86emu_halt_sys(emu); - } +#ifndef __NO_STRICT_ALIGNMENT + if ((addr & 3) != 0) + return (le32dec(va)); + else +#endif return (le32toh(*va)); } @@ -178,10 +188,8 @@ x86bios_emu_wrb(struct x86emu *emu, uint uint8_t *va; va = x86bios_get_pages(addr, sizeof(*va)); - if (va == NULL) { + if (va == NULL) x86bios_set_fault(emu, addr); - x86emu_halt_sys(emu); - } *va = val; } @@ -192,11 +200,14 @@ x86bios_emu_wrw(struct x86emu *emu, uint uint16_t *va; va = x86bios_get_pages(addr, sizeof(*va)); - if (va == NULL) { + if (va == NULL) x86bios_set_fault(emu, addr); - x86emu_halt_sys(emu); - } +#ifndef __NO_STRICT_ALIGNMENT + if ((addr & 1) != 0) + le16enc(va, val); + else +#endif *va = htole16(val); } @@ -206,11 +217,14 @@ x86bios_emu_wrl(struct x86emu *emu, uint uint32_t *va; va = x86bios_get_pages(addr, sizeof(*va)); - if (va == NULL) { + if (va == NULL) x86bios_set_fault(emu, addr); - x86emu_halt_sys(emu); - } +#ifndef __NO_STRICT_ALIGNMENT + if ((addr & 3) != 0) + le32enc(va, val); + else +#endif *va = htole32(val); } @@ -306,7 +320,7 @@ x86bios_alloc(uint32_t *offset, size_t s return (NULL); vaddr = contigmalloc(size, M_DEVBUF, M_NOWAIT, X86BIOS_RAM_BASE, - X86BIOS_ROM_BASE, X86BIOS_PAGE_SIZE, 0); + x86bios_rom_phys, X86BIOS_PAGE_SIZE, 0); if (vaddr != NULL) { *offset = vtophys(vaddr); x86bios_set_pages((vm_offset_t)vaddr, *offset, size); @@ -324,7 +338,7 @@ x86bios_free(void *addr, size_t size) return; paddr = vtophys(addr); - if (paddr < X86BIOS_RAM_BASE || paddr >= X86BIOS_ROM_BASE || + if (paddr < X86BIOS_RAM_BASE || paddr >= x86bios_rom_phys || paddr % X86BIOS_PAGE_SIZE != 0) return; @@ -338,7 +352,9 @@ x86bios_init_regs(struct x86regs *regs) { bzero(regs, sizeof(*regs)); - regs->X86BIOS_R_DS = regs->X86BIOS_R_SS = x86bios_seg_phys >> 4; + regs->X86BIOS_R_DS = 0x40; + regs->X86BIOS_R_SS = x86bios_seg_phys >> 4; + regs->X86BIOS_R_SP = 0xfffe; } void @@ -367,8 +383,9 @@ x86bios_call(struct x86regs *regs, uint1 (seg << 4) + off, regs->R_AX, regs->R_BX, regs->R_CX, regs->R_DX, regs->R_ES, regs->R_DI); if (x86bios_fault) - printf("Page fault at 0x%05x from 0x%05x.\n", - x86bios_fault_addr, x86bios_fault_inst); + printf("Page fault at 0x%05x from 0x%04x:0x%04x.\n", + x86bios_fault_addr, x86bios_fault_cs, + x86bios_fault_ip); } } @@ -411,8 +428,9 @@ x86bios_intr(struct x86regs *regs, int i intno, regs->R_AX, regs->R_BX, regs->R_CX, regs->R_DX, regs->R_ES, regs->R_DI); if (x86bios_fault) - printf("Page fault at 0x%05x from 0x%05x.\n", - x86bios_fault_addr, x86bios_fault_inst); + printf("Page fault at 0x%05x from 0x%04x:0x%04x.\n", + x86bios_fault_addr, x86bios_fault_cs, + x86bios_fault_ip); } } @@ -468,6 +486,12 @@ x86bios_match_device(uint32_t offset, de return (1); } +#if defined(__amd64__) || (defined(__i386__) && !defined(PC98)) +#define PROBE_EBDA 1 +#else +#define PROBE_EBDA 0 +#endif + static __inline int x86bios_map_mem(void) { @@ -475,18 +499,74 @@ x86bios_map_mem(void) x86bios_ivt = pmap_mapbios(X86BIOS_IVT_BASE, X86BIOS_IVT_SIZE); if (x86bios_ivt == NULL) return (1); - x86bios_rom = pmap_mapdev(X86BIOS_ROM_BASE, X86BIOS_ROM_SIZE); + +#if PROBE_EBDA + /* Probe EBDA via BDA. */ + x86bios_rom_phys = *(uint16_t *)((vm_offset_t)x86bios_ivt + 0x40e); + x86bios_rom_phys = le16toh(x86bios_rom_phys) << 4; + if (x86bios_rom_phys != 0 && x86bios_rom_phys < X86BIOS_ROM_BASE && + X86BIOS_ROM_BASE - x86bios_rom_phys <= 128 * 1024) + x86bios_rom_phys = + rounddown(x86bios_rom_phys, X86BIOS_PAGE_SIZE); + else +#endif + x86bios_rom_phys = X86BIOS_ROM_BASE; + x86bios_rom = pmap_mapdev(x86bios_rom_phys, X86BIOS_ROM_SIZE); if (x86bios_rom == NULL) { pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); return (1); } +#if PROBE_EBDA + /* Change attribute for EBDA. */ + if (x86bios_rom_phys < X86BIOS_ROM_BASE && + pmap_change_attr((vm_offset_t)x86bios_rom, + X86BIOS_ROM_BASE - x86bios_rom_phys, PAT_WRITE_BACK) != 0) { + pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); + pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE); + return (1); + } +#endif + /* Change attribute for high memory. */ + if (pmap_change_attr((vm_offset_t)x86bios_rom + X86BIOS_ROM_SIZE - + X86BIOS_SEG_SIZE, X86BIOS_SEG_SIZE, PAT_WRITE_BACK) != 0) { + pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); + pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE); + return (1); + } + x86bios_seg = contigmalloc(X86BIOS_SEG_SIZE, M_DEVBUF, M_WAITOK, - X86BIOS_RAM_BASE, X86BIOS_ROM_BASE, X86BIOS_PAGE_SIZE, 0); + X86BIOS_RAM_BASE, x86bios_rom_phys, X86BIOS_PAGE_SIZE, 0); x86bios_seg_phys = vtophys(x86bios_seg); + if (bootverbose) { + printf("x86bios: IVT 0x%06x-0x%06x at %p\n", + X86BIOS_IVT_BASE, X86BIOS_IVT_SIZE + X86BIOS_IVT_BASE - 1, + x86bios_ivt); + printf("x86bios: SSEG 0x%06x-0x%06x at %p\n", + (uint32_t)x86bios_seg_phys, + X86BIOS_SEG_SIZE + (uint32_t)x86bios_seg_phys - 1, + x86bios_seg); +#if PROBE_EBDA + if (x86bios_rom_phys < X86BIOS_ROM_BASE) + printf("x86bios: EBDA 0x%06x-0x%06x at %p\n", + (uint32_t)x86bios_rom_phys, X86BIOS_ROM_BASE - 1, + x86bios_rom); +#endif + printf("x86bios: ROM 0x%06x-0x%06x at %p\n", + X86BIOS_ROM_BASE, X86BIOS_MEM_SIZE - X86BIOS_SEG_SIZE - 1, + (void *)((vm_offset_t)x86bios_rom + X86BIOS_ROM_BASE - + x86bios_rom_phys)); + printf("x86bios: HIMEM 0x%06x-0x%06x at %p\n", + X86BIOS_MEM_SIZE - X86BIOS_SEG_SIZE, X86BIOS_MEM_SIZE - 1, + (void *)((vm_offset_t)x86bios_rom + X86BIOS_ROM_SIZE - + X86BIOS_SEG_SIZE)); + } + return (0); } +#undef PROBE_EBDA + static __inline void x86bios_unmap_mem(void) { @@ -510,7 +590,7 @@ x86bios_init(void *arg __unused) M_WAITOK | M_ZERO); x86bios_set_pages((vm_offset_t)x86bios_ivt, X86BIOS_IVT_BASE, X86BIOS_IVT_SIZE); - x86bios_set_pages((vm_offset_t)x86bios_rom, X86BIOS_ROM_BASE, + x86bios_set_pages((vm_offset_t)x86bios_rom, x86bios_rom_phys, X86BIOS_ROM_SIZE); x86bios_set_pages((vm_offset_t)x86bios_seg, x86bios_seg_phys, X86BIOS_SEG_SIZE);