mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-25 16:13:17 +00:00
Stop linking against a direct-mapped virtual address and instead
use the PBVM. This eliminates the implied hardcoding of the physical address at which the kernel needs to be loaded. Using the PBVM makes it possible to load the kernel irrespective of the physical memory organization and allows us to replicate kernel text on NUMA machines. While here, reduce the direct-mapped page size to the kernel's page size so that we can support memory attributes better.
This commit is contained in:
parent
627cecc5c9
commit
7df304f3e0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=221271
@ -92,6 +92,7 @@ ia64/ia64/locore.S standard no-obj
|
||||
ia64/ia64/machdep.c standard
|
||||
ia64/ia64/mca.c standard
|
||||
ia64/ia64/mem.c optional mem
|
||||
ia64/ia64/mp_locore.S optional smp
|
||||
ia64/ia64/mp_machdep.c optional smp
|
||||
ia64/ia64/nexus.c standard
|
||||
ia64/ia64/pal.S standard
|
||||
|
@ -3,7 +3,7 @@ OUTPUT_FORMAT("elf64-ia64-freebsd", "elf64-ia64-freebsd", "elf64-ia64-freebsd")
|
||||
OUTPUT_ARCH(ia64)
|
||||
ENTRY(__start)
|
||||
SEARCH_DIR(/usr/lib);
|
||||
kernel_text = 0xe000000004000000;
|
||||
kernel_text = 0x9ffc000000000000;
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
@ -11,10 +11,10 @@ SECTIONS
|
||||
.interp : { *(.interp) }
|
||||
|
||||
PROVIDE (btext = .);
|
||||
.ivt : { *(.ivt) }
|
||||
.text :
|
||||
{
|
||||
*(.text.ivt)
|
||||
*(.ivt)
|
||||
*(.ivt.text)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
@ -60,9 +60,11 @@ SECTIONS
|
||||
page in the loader virtual memory. */
|
||||
. = ALIGN(65536);
|
||||
|
||||
PROVIDE (bdata = .);
|
||||
.data :
|
||||
{
|
||||
*(.data.kstack .data .data.* .gnu.linkonce.d.*)
|
||||
*(.ivt.data)
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
|
@ -129,7 +129,7 @@ efi_boot_minimal(uint64_t systbl)
|
||||
setvirt = (void *)IA64_PHYS_TO_RR7((u_long)efi_runtime->rt_setvirtual);
|
||||
status = ia64_efi_physical(setvirt, bootinfo->bi_memmap_size,
|
||||
bootinfo->bi_memdesc_size, bootinfo->bi_memdesc_version,
|
||||
bootinfo->bi_memmap);
|
||||
ia64_tpa(bootinfo->bi_memmap));
|
||||
return ((status < 0) ? EFAULT : 0);
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ efi_md_first(void)
|
||||
|
||||
if (bootinfo->bi_memmap == 0)
|
||||
return (NULL);
|
||||
return ((struct efi_md *)IA64_PHYS_TO_RR7(bootinfo->bi_memmap));
|
||||
return ((struct efi_md *)bootinfo->bi_memmap);
|
||||
}
|
||||
|
||||
struct efi_md *
|
||||
@ -172,7 +172,7 @@ efi_md_next(struct efi_md *md)
|
||||
{
|
||||
uint64_t plim;
|
||||
|
||||
plim = IA64_PHYS_TO_RR7(bootinfo->bi_memmap + bootinfo->bi_memmap_size);
|
||||
plim = bootinfo->bi_memmap + bootinfo->bi_memmap_size;
|
||||
md = (struct efi_md *)((uintptr_t)md + bootinfo->bi_memdesc_size);
|
||||
return ((md >= (struct efi_md *)plim) ? NULL : md);
|
||||
}
|
||||
|
@ -48,9 +48,16 @@ __FBSDID("$FreeBSD$");
|
||||
* ar.k4 = PCPU data
|
||||
*/
|
||||
|
||||
.section .ivt.data, "aw"
|
||||
|
||||
.global pmap_ptc_g_sem
|
||||
pmap_ptc_g_sem: data8 0
|
||||
|
||||
.global ia64_kptdir
|
||||
ia64_kptdir: data8 0
|
||||
|
||||
#ifdef EXCEPTION_TRACING
|
||||
|
||||
.data
|
||||
.global xtrace, xhead
|
||||
xtrace: .space 1024*5*8
|
||||
xhead: data8 xtrace
|
||||
@ -101,7 +108,7 @@ xhead: data8 xtrace
|
||||
|
||||
#endif
|
||||
|
||||
.section .text.ivt, "ax"
|
||||
.section .ivt.text, "ax"
|
||||
|
||||
/*
|
||||
* exception_save: save interrupted state
|
||||
@ -129,7 +136,7 @@ ENTRY_NOPROFILE(exception_save, 0)
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
cmp.le p14,p15=5,r31
|
||||
cmp.le p14,p15=IA64_VM_MINKERN_REGION,r31
|
||||
;;
|
||||
(p15) mov r23=ar.k7 // kernel memory stack
|
||||
(p14) mov r23=sp
|
||||
@ -233,7 +240,7 @@ exception_save_restart:
|
||||
{ .mmi
|
||||
st8 [r30]=r19,16 // rnat
|
||||
st8 [r31]=r0,16 // __spare
|
||||
cmp.le p12,p13=5,r24
|
||||
cmp.le p12,p13=IA64_VM_MINKERN_REGION,r24
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
@ -602,7 +609,7 @@ ENTRY_NOPROFILE(exception_restore, 0)
|
||||
{ .mmi
|
||||
ld8.fill r1=[r30],16 // gp
|
||||
ld8 r27=[r31],16 // ndirty
|
||||
cmp.le p14,p15=5,r28
|
||||
cmp.le p14,p15=IA64_VM_MINKERN_REGION,r28
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
@ -915,7 +922,7 @@ IVT_ENTRY(Alternate_Instruction_TLB, 0x0c00)
|
||||
extr.u r17=r16,61,3 // get region number
|
||||
mov r19=PTE_PRESENT+PTE_ACCESSED+PTE_DIRTY+PTE_PL_KERN+PTE_AR_RWX
|
||||
;;
|
||||
cmp.eq p13,p0=4,r17 // RR4?
|
||||
cmp.eq p13,p0=IA64_PBVM_RR,r17 // RR4?
|
||||
(p13) br.cond.sptk.few 4f
|
||||
;;
|
||||
cmp.ge p13,p0=5,r17 // RR0-RR5?
|
||||
@ -958,7 +965,7 @@ IVT_ENTRY(Alternate_Data_TLB, 0x1000)
|
||||
extr.u r17=r16,61,3 // get region number
|
||||
mov r19=PTE_PRESENT+PTE_ACCESSED+PTE_DIRTY+PTE_PL_KERN+PTE_AR_RWX
|
||||
;;
|
||||
cmp.eq p13,p0=4,r17 // RR4?
|
||||
cmp.eq p13,p0=IA64_PBVM_RR,r17 // RR4?
|
||||
(p13) br.cond.sptk.few 4f
|
||||
;;
|
||||
cmp.ge p13,p0=5,r17 // RR0-RR5?
|
||||
@ -1007,21 +1014,22 @@ IVT_ENTRY(Data_Nested_TLB, 0x1400)
|
||||
// double nested faults. Since all virtual addresses we encounter
|
||||
// here are direct mapped region 7 addresses, we have no problem
|
||||
// constructing physical addresses.
|
||||
|
||||
{ .mlx
|
||||
rsm psr.dt
|
||||
nop 0
|
||||
movl r27=ia64_kptdir
|
||||
;;
|
||||
}
|
||||
{ .mii
|
||||
srlz.d
|
||||
dep r27=0,r27,61,3
|
||||
;;
|
||||
ld8 r27=[r27]
|
||||
extr.u r28=r30,3*PAGE_SHIFT-8, PAGE_SHIFT-3 // dir L0 index
|
||||
}
|
||||
{ .mii
|
||||
ld8 r27=[r27] // dir L0 page
|
||||
extr.u r26=r30,2*PAGE_SHIFT-5, PAGE_SHIFT-3 // dir L1 index
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
rsm psr.dt
|
||||
;;
|
||||
srlz.d
|
||||
dep r27=0,r27,61,3
|
||||
;;
|
||||
}
|
||||
|
@ -77,13 +77,13 @@ ASSYM(ERESTART, ERESTART);
|
||||
|
||||
ASSYM(FRAME_SYSCALL, FRAME_SYSCALL);
|
||||
|
||||
ASSYM(IA64_ID_PAGE_SHIFT, IA64_ID_PAGE_SHIFT);
|
||||
|
||||
ASSYM(IA64_PBVM_BASE, IA64_PBVM_BASE);
|
||||
ASSYM(IA64_PBVM_PAGE_SHIFT, IA64_PBVM_PAGE_SHIFT);
|
||||
ASSYM(IA64_PBVM_PGTBL, IA64_PBVM_PGTBL);
|
||||
ASSYM(IA64_PBVM_RR, IA64_PBVM_RR);
|
||||
|
||||
ASSYM(IA64_VM_MINKERN_REGION, IA64_VM_MINKERN_REGION);
|
||||
|
||||
ASSYM(KSTACK_PAGES, KSTACK_PAGES);
|
||||
|
||||
ASSYM(MC_PRESERVED, offsetof(mcontext_t, mc_preserved));
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2001-2011 Marcel Moolenaar
|
||||
* Copyright (c) 1998 Doug Rabson
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -26,12 +27,10 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <machine/asm.h>
|
||||
#include <machine/ia64_cpu.h>
|
||||
#include <machine/intrcnt.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/intrcnt.h>
|
||||
#include <assym.s>
|
||||
|
||||
/*
|
||||
@ -40,7 +39,7 @@
|
||||
*/
|
||||
#define FW_STACK_SIZE 3*PAGE_SIZE
|
||||
|
||||
.section .data.kstack, "aw"
|
||||
.section .ivt.data, "aw"
|
||||
.align PAGE_SIZE
|
||||
.global kstack
|
||||
kstack: .space FW_STACK_SIZE
|
||||
@ -82,7 +81,7 @@ ENTRY_NOPROFILE(__start, 1)
|
||||
}
|
||||
{ .mlx
|
||||
mov ar.bspstore=r16 // switch backing store
|
||||
movl r16=pa_bootinfo
|
||||
movl r16=bootinfo
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
@ -187,124 +186,6 @@ enter_userland:
|
||||
}
|
||||
END(fork_trampoline)
|
||||
|
||||
#ifdef SMP
|
||||
/*
|
||||
* AP wake-up entry point. The handoff state is similar as for the BSP,
|
||||
* as described on page 3-9 of the IPF SAL Specification. The difference
|
||||
* lies in the contents of register b0. For APs this register holds the
|
||||
* return address into the SAL rendezvous routine.
|
||||
*
|
||||
* Note that we're responsible for clearing the IRR bit by reading cr.ivr
|
||||
* and issuing the EOI to the local SAPIC.
|
||||
*/
|
||||
.align 32
|
||||
ENTRY_NOPROFILE(os_boot_rendez,0)
|
||||
mov r16=cr.ivr // clear IRR bit
|
||||
;;
|
||||
srlz.d
|
||||
mov cr.eoi=r0 // ACK the wake-up
|
||||
;;
|
||||
srlz.d
|
||||
rsm IA64_PSR_IC|IA64_PSR_I
|
||||
;;
|
||||
mov r16 = (5<<8)|(PAGE_SHIFT<<2)|1
|
||||
movl r17 = 5<<61
|
||||
;;
|
||||
mov rr[r17] = r16
|
||||
;;
|
||||
srlz.d
|
||||
mov r16 = (6<<8)|(IA64_ID_PAGE_SHIFT<<2)
|
||||
movl r17 = 6<<61
|
||||
;;
|
||||
mov rr[r17] = r16
|
||||
;;
|
||||
srlz.d
|
||||
mov r16 = (7<<8)|(IA64_ID_PAGE_SHIFT<<2)
|
||||
movl r17 = 7<<61
|
||||
;;
|
||||
mov rr[r17] = r16
|
||||
;;
|
||||
srlz.d
|
||||
mov r18 = 28<<2
|
||||
movl r16 = PTE_PRESENT+PTE_MA_WB+PTE_ACCESSED+PTE_DIRTY+ \
|
||||
PTE_PL_KERN+PTE_AR_RWX+PTE_ED
|
||||
;;
|
||||
mov cr.ifa = r17
|
||||
mov cr.itir = r18
|
||||
ptr.d r17, r18
|
||||
ptr.i r17, r18
|
||||
;;
|
||||
srlz.i
|
||||
;;
|
||||
itr.d dtr[r0] = r16
|
||||
mov r18 = IA64_DCR_DEFAULT
|
||||
;;
|
||||
itr.i itr[r0] = r16
|
||||
mov cr.dcr = r18
|
||||
;;
|
||||
srlz.i
|
||||
;;
|
||||
1: mov r16 = ip
|
||||
add r17 = 2f-1b, r17
|
||||
movl r18 = (IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_DFH|IA64_PSR_DT|IA64_PSR_IC|IA64_PSR_IT|IA64_PSR_RT)
|
||||
;;
|
||||
add r17 = r17, r16
|
||||
mov cr.ipsr = r18
|
||||
mov cr.ifs = r0
|
||||
;;
|
||||
mov cr.iip = r17
|
||||
;;
|
||||
rfi
|
||||
|
||||
.align 32
|
||||
2:
|
||||
{ .mlx
|
||||
mov ar.rsc = 0
|
||||
movl r16 = ia64_vector_table // set up IVT early
|
||||
;;
|
||||
}
|
||||
{ .mlx
|
||||
mov cr.iva = r16
|
||||
movl r16 = ap_stack
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.i
|
||||
;;
|
||||
ld8 r16 = [r16]
|
||||
mov r18 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
|
||||
;;
|
||||
}
|
||||
{ .mlx
|
||||
mov ar.bspstore = r16
|
||||
movl gp = __gp
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
loadrs
|
||||
;;
|
||||
alloc r17 = ar.pfs, 0, 0, 0, 0
|
||||
add sp = r18, r16
|
||||
;;
|
||||
}
|
||||
{ .mib
|
||||
mov ar.rsc = 3
|
||||
nop 0
|
||||
br.call.sptk.few rp = ia64_ap_startup
|
||||
;;
|
||||
}
|
||||
/* NOT REACHED */
|
||||
9:
|
||||
{ .mib
|
||||
nop 0
|
||||
nop 0
|
||||
br.sptk 9b
|
||||
;;
|
||||
}
|
||||
END(os_boot_rendez)
|
||||
|
||||
#endif /* !SMP */
|
||||
|
||||
/*
|
||||
* Create a default interrupt name table. The first entry (vector 0) is
|
||||
* hardwaired to the clock interrupt.
|
||||
|
@ -115,7 +115,6 @@ SYSCTL_UINT(_hw_freq, OID_AUTO, itc, CTLFLAG_RD, &itc_freq, 0,
|
||||
|
||||
int cold = 1;
|
||||
|
||||
u_int64_t pa_bootinfo;
|
||||
struct bootinfo *bootinfo;
|
||||
|
||||
struct pcpu pcpu0;
|
||||
@ -128,8 +127,9 @@ extern u_int64_t epc_sigtramp[];
|
||||
|
||||
struct fpswa_iface *fpswa_iface;
|
||||
|
||||
u_int64_t ia64_pal_base;
|
||||
u_int64_t ia64_port_base;
|
||||
vm_size_t ia64_pal_size;
|
||||
vm_paddr_t ia64_pal_base;
|
||||
vm_offset_t ia64_port_base;
|
||||
|
||||
u_int64_t ia64_lapic_addr = PAL_PIB_DEFAULT_ADDR;
|
||||
|
||||
@ -548,15 +548,15 @@ map_vhpt(uintptr_t vhpt)
|
||||
pte |= vhpt & PTE_PPN_MASK;
|
||||
|
||||
__asm __volatile("ptr.d %0,%1" :: "r"(vhpt),
|
||||
"r"(IA64_ID_PAGE_SHIFT<<2));
|
||||
"r"(pmap_vhpt_log2size << 2));
|
||||
|
||||
__asm __volatile("mov %0=psr" : "=r"(psr));
|
||||
__asm __volatile("rsm psr.ic|psr.i");
|
||||
ia64_srlz_i();
|
||||
ia64_set_ifa(vhpt);
|
||||
ia64_set_itir(IA64_ID_PAGE_SHIFT << 2);
|
||||
ia64_set_itir(pmap_vhpt_log2size << 2);
|
||||
ia64_srlz_d();
|
||||
__asm __volatile("itr.d dtr[%0]=%1" :: "r"(2), "r"(pte));
|
||||
__asm __volatile("itr.d dtr[%0]=%1" :: "r"(3), "r"(pte));
|
||||
__asm __volatile("mov psr.l=%0" :: "r" (psr));
|
||||
ia64_srlz_i();
|
||||
}
|
||||
@ -565,25 +565,36 @@ void
|
||||
map_pal_code(void)
|
||||
{
|
||||
pt_entry_t pte;
|
||||
vm_offset_t va;
|
||||
vm_size_t sz;
|
||||
uint64_t psr;
|
||||
u_int shft;
|
||||
|
||||
if (ia64_pal_base == 0)
|
||||
if (ia64_pal_size == 0)
|
||||
return;
|
||||
|
||||
va = IA64_PHYS_TO_RR7(ia64_pal_base);
|
||||
|
||||
sz = ia64_pal_size;
|
||||
shft = 0;
|
||||
while (sz > 1) {
|
||||
shft++;
|
||||
sz >>= 1;
|
||||
}
|
||||
|
||||
pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY |
|
||||
PTE_PL_KERN | PTE_AR_RWX;
|
||||
pte |= ia64_pal_base & PTE_PPN_MASK;
|
||||
|
||||
__asm __volatile("ptr.d %0,%1; ptr.i %0,%1" ::
|
||||
"r"(IA64_PHYS_TO_RR7(ia64_pal_base)), "r"(IA64_ID_PAGE_SHIFT<<2));
|
||||
__asm __volatile("ptr.d %0,%1; ptr.i %0,%1" :: "r"(va), "r"(shft<<2));
|
||||
|
||||
__asm __volatile("mov %0=psr" : "=r"(psr));
|
||||
__asm __volatile("rsm psr.ic|psr.i");
|
||||
ia64_srlz_i();
|
||||
ia64_set_ifa(IA64_PHYS_TO_RR7(ia64_pal_base));
|
||||
ia64_set_itir(IA64_ID_PAGE_SHIFT << 2);
|
||||
ia64_set_ifa(va);
|
||||
ia64_set_itir(shft << 2);
|
||||
ia64_srlz_d();
|
||||
__asm __volatile("itr.d dtr[%0]=%1" :: "r"(1), "r"(pte));
|
||||
__asm __volatile("itr.d dtr[%0]=%1" :: "r"(4), "r"(pte));
|
||||
ia64_srlz_d();
|
||||
__asm __volatile("itr.i itr[%0]=%1" :: "r"(1), "r"(pte));
|
||||
__asm __volatile("mov psr.l=%0" :: "r" (psr));
|
||||
@ -598,7 +609,7 @@ map_gateway_page(void)
|
||||
|
||||
pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY |
|
||||
PTE_PL_KERN | PTE_AR_X_RX;
|
||||
pte |= (uint64_t)ia64_gateway_page & PTE_PPN_MASK;
|
||||
pte |= ia64_tpa((uint64_t)ia64_gateway_page) & PTE_PPN_MASK;
|
||||
|
||||
__asm __volatile("ptr.d %0,%1; ptr.i %0,%1" ::
|
||||
"r"(VM_MAXUSER_ADDRESS), "r"(PAGE_SHIFT << 2));
|
||||
@ -609,9 +620,9 @@ map_gateway_page(void)
|
||||
ia64_set_ifa(VM_MAXUSER_ADDRESS);
|
||||
ia64_set_itir(PAGE_SHIFT << 2);
|
||||
ia64_srlz_d();
|
||||
__asm __volatile("itr.d dtr[%0]=%1" :: "r"(3), "r"(pte));
|
||||
__asm __volatile("itr.d dtr[%0]=%1" :: "r"(5), "r"(pte));
|
||||
ia64_srlz_d();
|
||||
__asm __volatile("itr.i itr[%0]=%1" :: "r"(3), "r"(pte));
|
||||
__asm __volatile("itr.i itr[%0]=%1" :: "r"(2), "r"(pte));
|
||||
__asm __volatile("mov psr.l=%0" :: "r" (psr));
|
||||
ia64_srlz_i();
|
||||
|
||||
@ -680,17 +691,6 @@ ia64_init(void)
|
||||
* information provided by the boot program).
|
||||
*/
|
||||
|
||||
/*
|
||||
* pa_bootinfo is the physical address of the bootinfo block as
|
||||
* passed to us by the loader and set in locore.s.
|
||||
*/
|
||||
bootinfo = (struct bootinfo *)(IA64_PHYS_TO_RR7(pa_bootinfo));
|
||||
|
||||
if (bootinfo->bi_magic != BOOTINFO_MAGIC || bootinfo->bi_version != 1) {
|
||||
bzero(bootinfo, sizeof(*bootinfo));
|
||||
bootinfo->bi_kernend = (vm_offset_t)round_page(_end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the I/O ports first - we need them for console
|
||||
* probing.
|
||||
@ -702,6 +702,7 @@ ia64_init(void)
|
||||
md->md_pages * EFI_PAGE_SIZE);
|
||||
break;
|
||||
case EFI_MD_TYPE_PALCODE:
|
||||
ia64_pal_size = md->md_pages * EFI_PAGE_SIZE;
|
||||
ia64_pal_base = md->md_phys;
|
||||
break;
|
||||
}
|
||||
@ -742,34 +743,14 @@ ia64_init(void)
|
||||
kernend = round_page(bootinfo->bi_kernend);
|
||||
|
||||
/*
|
||||
* Setup the PCPU data for the bootstrap processor. It is needed
|
||||
* by printf(). Also, since printf() has critical sections, we
|
||||
* need to initialize at least pc_curthread.
|
||||
* Region 6 is direct mapped UC and region 7 is direct mapped
|
||||
* WC. The details of this is controlled by the Alt {I,D}TLB
|
||||
* handlers. Here we just make sure that they have the largest
|
||||
* possible page size to minimise TLB usage.
|
||||
*/
|
||||
pcpup = &pcpu0;
|
||||
ia64_set_k4((u_int64_t)pcpup);
|
||||
pcpu_init(pcpup, 0, sizeof(pcpu0));
|
||||
dpcpu_init((void *)kernend, 0);
|
||||
kernend += DPCPU_SIZE;
|
||||
PCPU_SET(curthread, &thread0);
|
||||
|
||||
/*
|
||||
* Initialize the console before we print anything out.
|
||||
*/
|
||||
cninit();
|
||||
|
||||
/* OUTPUT NOW ALLOWED */
|
||||
|
||||
if (ia64_pal_base != 0) {
|
||||
ia64_pal_base &= ~IA64_ID_PAGE_MASK;
|
||||
/*
|
||||
* We use a TR to map the first 256M of memory - this might
|
||||
* cover the palcode too.
|
||||
*/
|
||||
if (ia64_pal_base == 0)
|
||||
printf("PAL code mapped by the kernel's TR\n");
|
||||
} else
|
||||
printf("PAL code not found\n");
|
||||
ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (PAGE_SHIFT << 2));
|
||||
ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (PAGE_SHIFT << 2));
|
||||
ia64_srlz_d();
|
||||
|
||||
/*
|
||||
* Wire things up so we can call the firmware.
|
||||
@ -780,6 +761,26 @@ ia64_init(void)
|
||||
ia64_sal_init();
|
||||
calculate_frequencies();
|
||||
|
||||
/*
|
||||
* Setup the PCPU data for the bootstrap processor. It is needed
|
||||
* by printf(). Also, since printf() has critical sections, we
|
||||
* need to initialize at least pc_curthread.
|
||||
*/
|
||||
pcpup = &pcpu0;
|
||||
ia64_set_k4((u_int64_t)pcpup);
|
||||
pcpu_init(pcpup, 0, sizeof(pcpu0));
|
||||
dpcpu_init((void *)kernend, 0);
|
||||
PCPU_SET(md.lid, ia64_get_lid());
|
||||
kernend += DPCPU_SIZE;
|
||||
PCPU_SET(curthread, &thread0);
|
||||
|
||||
/*
|
||||
* Initialize the console before we print anything out.
|
||||
*/
|
||||
cninit();
|
||||
|
||||
/* OUTPUT NOW ALLOWED */
|
||||
|
||||
if (metadata_missing)
|
||||
printf("WARNING: loader(8) metadata is missing!\n");
|
||||
|
||||
|
275
sys/ia64/ia64/mp_locore.S
Normal file
275
sys/ia64/ia64/mp_locore.S
Normal file
@ -0,0 +1,275 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Marcel Moolenaar
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include <machine/ia64_cpu.h>
|
||||
#include <machine/pte.h>
|
||||
#include <assym.s>
|
||||
|
||||
/*
|
||||
* AP wake-up entry point. The handoff state is similar as for the BSP,
|
||||
* as described on page 3-9 of the IPF SAL Specification. The difference
|
||||
* lies in the contents of register b0. For APs this register holds the
|
||||
* return address into the SAL rendezvous routine.
|
||||
*
|
||||
* Note that we're responsible for clearing the IRR bit by reading cr.ivr
|
||||
* and issuing the EOI to the local SAPIC.
|
||||
*/
|
||||
.align 32
|
||||
ENTRY_NOPROFILE(os_boot_rendez,0)
|
||||
{ .mmi
|
||||
st8 [gp] = gp // trace = 0x00
|
||||
mov r8 = cr.ivr // clear IRR bit
|
||||
add r2 = 8, gp
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.d
|
||||
mov cr.eoi = r0 // ACK the wake-up
|
||||
add r3 = 16, gp
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.d
|
||||
rsm IA64_PSR_IC | IA64_PSR_I
|
||||
mov r16 = (IA64_PBVM_RR << 8) | (IA64_PBVM_PAGE_SHIFT << 2)
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.d
|
||||
st8 [gp] = r2 // trace = 0x08
|
||||
dep.z r17 = IA64_PBVM_RR, 61, 3
|
||||
;;
|
||||
}
|
||||
{ .mlx
|
||||
mov rr[r17] = r16
|
||||
movl r18 = IA64_PBVM_PGTBL
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.i
|
||||
;;
|
||||
st8 [gp] = r3 // trace = 0x10
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
ld8 r16 = [r2], 16 // as_pgtbl_pte
|
||||
ld8 r17 = [r3], 16 // as_pgtbl_itir
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
mov cr.itir = r17
|
||||
mov cr.ifa = r18
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.d
|
||||
ptr.d r18, r17
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.d
|
||||
st8 [gp] = r2 // trace = 0x18
|
||||
mov r8 = r0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
itr.d dtr[r8] = r16
|
||||
;;
|
||||
srlz.d
|
||||
mov r9 = r0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
ld8 r16 = [r2], 16 // as_text_va
|
||||
st8 [gp] = r3 // trace = 0x20
|
||||
add r8 = 1, r8
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
ld8 r17 = [r3], 16 // as_text_pte
|
||||
ld8 r18 = [r2], 16 // as_text_itir
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
mov cr.ifa = r16
|
||||
mov cr.itir = r18
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.d
|
||||
ptr.d r16, r18
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.d
|
||||
st8 [gp] = r3 // trace = 0x30
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
itr.d dtr[r8] = r17
|
||||
;;
|
||||
srlz.d
|
||||
nop 0
|
||||
}
|
||||
{ .mmi
|
||||
st8 [gp] = r2 // trace = 0x38
|
||||
ptr.i r16, r18
|
||||
add r8 = 1, r8
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.i
|
||||
;;
|
||||
itr.i itr[r9] = r17
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
srlz.i
|
||||
;;
|
||||
ld8 r16 = [r3], 16 // as_data_va
|
||||
add r9 = 1, r9
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
st8 [gp] = r3 // trace = 0x40
|
||||
ld8 r17 = [r2], 16 // as_data_pte
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
mov cr.ifa = r16
|
||||
ld8 r18 = [r3], 16 // as_data_itir
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
mov cr.itir = r18
|
||||
;;
|
||||
srlz.d
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
ptr.d r16, r18
|
||||
;;
|
||||
srlz.d
|
||||
mov r19 = IA64_DCR_DEFAULT
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
itr.d dtr[r8] = r17
|
||||
;;
|
||||
srlz.d
|
||||
add r8 = 1, r8
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
st8 [gp] = r2 // trace = 0x48
|
||||
;;
|
||||
ld8 r16 = [r2], 16 // as_kstack
|
||||
nop 0
|
||||
}
|
||||
{ .mmi
|
||||
ld8 r17 = [r3], 16 // as_kstack_top
|
||||
mov cr.dcr = r19
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mlx
|
||||
srlz.i
|
||||
movl r18 = IA64_PSR_BN | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_IC | \
|
||||
IA64_PSR_RT | IA64_PSR_DFH
|
||||
;;
|
||||
}
|
||||
{ .mlx
|
||||
mov cr.ipsr = r18
|
||||
movl r19 = ia64_vector_table // set up IVT early
|
||||
;;
|
||||
}
|
||||
{ .mlx
|
||||
mov cr.iva = r19
|
||||
movl r18 = 1f
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
mov cr.iip = r18
|
||||
mov cr.ifs = r0
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmb
|
||||
srlz.d
|
||||
st8 [gp] = r2 // trace = 0x58
|
||||
rfi
|
||||
;;
|
||||
}
|
||||
|
||||
.align 32
|
||||
1:
|
||||
{ .mlx
|
||||
mov ar.bspstore = r16
|
||||
movl gp = __gp
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
loadrs
|
||||
add sp = -16, r17
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mmi
|
||||
mov ar.rsc = 3
|
||||
;;
|
||||
alloc r18 = ar.pfs, 0, 0, 0, 0
|
||||
;;
|
||||
}
|
||||
{ .mib
|
||||
nop 0
|
||||
nop 0
|
||||
br.call.sptk.few rp = ia64_ap_startup
|
||||
;;
|
||||
}
|
||||
/* NOT REACHED */
|
||||
9:
|
||||
{ .mib
|
||||
nop 0
|
||||
nop 0
|
||||
br.sptk 9b
|
||||
;;
|
||||
}
|
||||
END(os_boot_rendez)
|
@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/uuid.h>
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/bootinfo.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/fpu.h>
|
||||
#include <machine/intr.h>
|
||||
@ -62,22 +63,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
|
||||
extern uint64_t bdata[];
|
||||
|
||||
MALLOC_DEFINE(M_SMP, "SMP", "SMP related allocations");
|
||||
|
||||
void ia64_ap_startup(void);
|
||||
|
||||
#define LID_SAPIC(x) ((u_int)((x) >> 16))
|
||||
#define LID_SAPIC_ID(x) ((u_int)((x) >> 24) & 0xff)
|
||||
#define LID_SAPIC_EID(x) ((u_int)((x) >> 16) & 0xff)
|
||||
#define LID_SAPIC_SET(id,eid) (((id & 0xff) << 8 | (eid & 0xff)) << 16);
|
||||
#define LID_SAPIC_MASK 0xffff0000UL
|
||||
#define SAPIC_ID_GET_ID(x) ((u_int)((x) >> 8) & 0xff)
|
||||
#define SAPIC_ID_GET_EID(x) ((u_int)(x) & 0xff)
|
||||
#define SAPIC_ID_SET(id, eid) ((u_int)(((id) & 0xff) << 8) | ((eid) & 0xff))
|
||||
|
||||
/* Variables used by os_boot_rendez and ia64_ap_startup */
|
||||
struct pcpu *ap_pcpu;
|
||||
void *ap_stack;
|
||||
volatile int ap_delay;
|
||||
volatile int ap_awake;
|
||||
volatile int ap_spin;
|
||||
/* State used to wake and bootstrap APs. */
|
||||
struct ia64_ap_state ia64_ap_state;
|
||||
|
||||
int ia64_ipi_ast;
|
||||
int ia64_ipi_highfp;
|
||||
@ -86,6 +83,21 @@ int ia64_ipi_preempt;
|
||||
int ia64_ipi_rndzvs;
|
||||
int ia64_ipi_stop;
|
||||
|
||||
static u_int
|
||||
sz2shft(uint64_t sz)
|
||||
{
|
||||
uint64_t s;
|
||||
u_int shft;
|
||||
|
||||
shft = 12; /* Start with 4K */
|
||||
s = 1 << shft;
|
||||
while (s < sz) {
|
||||
shft++;
|
||||
s <<= 1;
|
||||
}
|
||||
return (shft);
|
||||
}
|
||||
|
||||
static u_int
|
||||
ia64_ih_ast(struct thread *td, u_int xiv, struct trapframe *tf)
|
||||
{
|
||||
@ -180,16 +192,27 @@ ia64_ap_startup(void)
|
||||
{
|
||||
uint64_t vhpt;
|
||||
|
||||
pcpup = ap_pcpu;
|
||||
ia64_ap_state.as_trace = 0x100;
|
||||
|
||||
ia64_set_rr(IA64_RR_BASE(5), (5 << 8) | (PAGE_SHIFT << 2) | 1);
|
||||
ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (PAGE_SHIFT << 2));
|
||||
ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (PAGE_SHIFT << 2));
|
||||
ia64_srlz_d();
|
||||
|
||||
pcpup = ia64_ap_state.as_pcpu;
|
||||
ia64_set_k4((intptr_t)pcpup);
|
||||
|
||||
ia64_ap_state.as_trace = 0x108;
|
||||
|
||||
vhpt = PCPU_GET(md.vhpt);
|
||||
map_vhpt(vhpt);
|
||||
ia64_set_pta(vhpt + (1 << 8) + (pmap_vhpt_log2size << 2) + 1);
|
||||
ia64_srlz_i();
|
||||
|
||||
ap_awake = 1;
|
||||
ap_delay = 0;
|
||||
ia64_ap_state.as_trace = 0x110;
|
||||
|
||||
ia64_ap_state.as_awake = 1;
|
||||
ia64_ap_state.as_delay = 0;
|
||||
|
||||
map_pal_code();
|
||||
map_gateway_page();
|
||||
@ -197,14 +220,14 @@ ia64_ap_startup(void)
|
||||
ia64_set_fpsr(IA64_FPSR_DEFAULT);
|
||||
|
||||
/* Wait until it's time for us to be unleashed */
|
||||
while (ap_spin)
|
||||
while (ia64_ap_state.as_spin)
|
||||
cpu_spinwait();
|
||||
|
||||
/* Initialize curthread. */
|
||||
KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
|
||||
PCPU_SET(curthread, PCPU_GET(idlethread));
|
||||
|
||||
atomic_add_int(&ap_awake, 1);
|
||||
atomic_add_int(&ia64_ap_state.as_awake, 1);
|
||||
while (!smp_started)
|
||||
cpu_spinwait();
|
||||
|
||||
@ -253,18 +276,18 @@ cpu_mp_probe(void)
|
||||
}
|
||||
|
||||
void
|
||||
cpu_mp_add(u_int acpiid, u_int apicid, u_int apiceid)
|
||||
cpu_mp_add(u_int acpi_id, u_int id, u_int eid)
|
||||
{
|
||||
struct pcpu *pc;
|
||||
u_int64_t lid;
|
||||
void *dpcpu;
|
||||
u_int cpuid;
|
||||
u_int cpuid, sapic_id;
|
||||
|
||||
lid = LID_SAPIC_SET(apicid, apiceid);
|
||||
cpuid = ((ia64_get_lid() & LID_SAPIC_MASK) == lid) ? 0 : smp_cpus++;
|
||||
sapic_id = SAPIC_ID_SET(id, eid);
|
||||
cpuid = (IA64_LID_GET_SAPIC_ID(ia64_get_lid()) == sapic_id)
|
||||
? 0 : smp_cpus++;
|
||||
|
||||
KASSERT((all_cpus & (1UL << cpuid)) == 0,
|
||||
("%s: cpu%d already in CPU map", __func__, acpiid));
|
||||
("%s: cpu%d already in CPU map", __func__, acpi_id));
|
||||
|
||||
if (cpuid != 0) {
|
||||
pc = (struct pcpu *)malloc(sizeof(*pc), M_SMP, M_WAITOK);
|
||||
@ -274,23 +297,26 @@ cpu_mp_add(u_int acpiid, u_int apicid, u_int apiceid)
|
||||
} else
|
||||
pc = pcpup;
|
||||
|
||||
pc->pc_acpi_id = acpiid;
|
||||
pc->pc_md.lid = lid;
|
||||
all_cpus |= (1UL << cpuid);
|
||||
pc->pc_acpi_id = acpi_id;
|
||||
pc->pc_md.lid = IA64_LID_SET_SAPIC_ID(sapic_id);
|
||||
|
||||
all_cpus |= (1UL << pc->pc_cpuid);
|
||||
}
|
||||
|
||||
void
|
||||
cpu_mp_announce()
|
||||
{
|
||||
struct pcpu *pc;
|
||||
uint32_t sapic_id;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= mp_maxid; i++) {
|
||||
pc = pcpu_find(i);
|
||||
if (pc != NULL) {
|
||||
sapic_id = IA64_LID_GET_SAPIC_ID(pc->pc_md.lid);
|
||||
printf("cpu%d: ACPI Id=%x, SAPIC Id=%x, SAPIC Eid=%x",
|
||||
i, pc->pc_acpi_id, LID_SAPIC_ID(pc->pc_md.lid),
|
||||
LID_SAPIC_EID(pc->pc_md.lid));
|
||||
i, pc->pc_acpi_id, SAPIC_ID_GET_ID(sapic_id),
|
||||
SAPIC_ID_GET_EID(sapic_id));
|
||||
if (i == 0)
|
||||
printf(" (BSP)\n");
|
||||
else
|
||||
@ -302,41 +328,76 @@ cpu_mp_announce()
|
||||
void
|
||||
cpu_mp_start()
|
||||
{
|
||||
struct ia64_sal_result result;
|
||||
struct ia64_fdesc *fd;
|
||||
struct pcpu *pc;
|
||||
uintptr_t state;
|
||||
u_char *stp;
|
||||
|
||||
ap_spin = 1;
|
||||
state = ia64_tpa((uintptr_t)&ia64_ap_state);
|
||||
fd = (struct ia64_fdesc *) os_boot_rendez;
|
||||
result = ia64_sal_entry(SAL_SET_VECTORS, SAL_OS_BOOT_RENDEZ,
|
||||
ia64_tpa(fd->func), state, 0, 0, 0, 0);
|
||||
|
||||
ia64_ap_state.as_pgtbl_pte = PTE_PRESENT | PTE_MA_WB |
|
||||
PTE_ACCESSED | PTE_DIRTY | PTE_PL_KERN | PTE_AR_RW |
|
||||
(bootinfo->bi_pbvm_pgtbl & PTE_PPN_MASK);
|
||||
ia64_ap_state.as_pgtbl_itir = sz2shft(bootinfo->bi_pbvm_pgtblsz) << 2;
|
||||
ia64_ap_state.as_text_va = IA64_PBVM_BASE;
|
||||
ia64_ap_state.as_text_pte = PTE_PRESENT | PTE_MA_WB |
|
||||
PTE_ACCESSED | PTE_DIRTY | PTE_PL_KERN | PTE_AR_RX |
|
||||
(ia64_tpa(IA64_PBVM_BASE) & PTE_PPN_MASK);
|
||||
ia64_ap_state.as_text_itir = bootinfo->bi_text_mapped << 2;
|
||||
ia64_ap_state.as_data_va = (uintptr_t)bdata;
|
||||
ia64_ap_state.as_data_pte = PTE_PRESENT | PTE_MA_WB |
|
||||
PTE_ACCESSED | PTE_DIRTY | PTE_PL_KERN | PTE_AR_RW |
|
||||
(ia64_tpa((uintptr_t)bdata) & PTE_PPN_MASK);
|
||||
ia64_ap_state.as_data_itir = bootinfo->bi_data_mapped << 2;
|
||||
|
||||
/* Keep 'em spinning until we unleash them... */
|
||||
ia64_ap_state.as_spin = 1;
|
||||
|
||||
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
|
||||
pc->pc_md.current_pmap = kernel_pmap;
|
||||
pc->pc_other_cpus = all_cpus & ~pc->pc_cpumask;
|
||||
if (pc->pc_cpuid > 0) {
|
||||
ap_pcpu = pc;
|
||||
pc->pc_md.vhpt = pmap_alloc_vhpt();
|
||||
if (pc->pc_md.vhpt == 0) {
|
||||
printf("SMP: WARNING: unable to allocate VHPT"
|
||||
" for cpu%d", pc->pc_cpuid);
|
||||
continue;
|
||||
}
|
||||
ap_stack = malloc(KSTACK_PAGES * PAGE_SIZE, M_SMP,
|
||||
M_WAITOK);
|
||||
ap_delay = 2000;
|
||||
ap_awake = 0;
|
||||
|
||||
if (bootverbose)
|
||||
printf("SMP: waking up cpu%d\n", pc->pc_cpuid);
|
||||
|
||||
ipi_send(pc, ia64_ipi_wakeup);
|
||||
|
||||
do {
|
||||
DELAY(1000);
|
||||
} while (--ap_delay > 0);
|
||||
pc->pc_md.awake = ap_awake;
|
||||
|
||||
if (!ap_awake)
|
||||
printf("SMP: WARNING: cpu%d did not wake up\n",
|
||||
pc->pc_cpuid);
|
||||
} else
|
||||
/* The BSP is obviously running already. */
|
||||
if (pc->pc_cpuid == 0) {
|
||||
pc->pc_md.awake = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
ia64_ap_state.as_pcpu = pc;
|
||||
pc->pc_md.vhpt = pmap_alloc_vhpt();
|
||||
if (pc->pc_md.vhpt == 0) {
|
||||
printf("SMP: WARNING: unable to allocate VHPT"
|
||||
" for cpu%d", pc->pc_cpuid);
|
||||
continue;
|
||||
}
|
||||
|
||||
stp = malloc(KSTACK_PAGES * PAGE_SIZE, M_SMP, M_WAITOK);
|
||||
ia64_ap_state.as_kstack = stp;
|
||||
ia64_ap_state.as_kstack_top = stp + KSTACK_PAGES * PAGE_SIZE;
|
||||
|
||||
ia64_ap_state.as_trace = 0;
|
||||
ia64_ap_state.as_delay = 2000;
|
||||
ia64_ap_state.as_awake = 0;
|
||||
|
||||
if (bootverbose)
|
||||
printf("SMP: waking up cpu%d\n", pc->pc_cpuid);
|
||||
|
||||
/* Here she goes... */
|
||||
ipi_send(pc, ia64_ipi_wakeup);
|
||||
do {
|
||||
DELAY(1000);
|
||||
} while (--ia64_ap_state.as_delay > 0);
|
||||
|
||||
pc->pc_md.awake = ia64_ap_state.as_awake;
|
||||
|
||||
if (!ia64_ap_state.as_awake) {
|
||||
printf("SMP: WARNING: cpu%d did not wake up (code "
|
||||
"%#lx)\n", pc->pc_cpuid,
|
||||
ia64_ap_state.as_trace - state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,10 +433,10 @@ cpu_mp_unleash(void *dummy)
|
||||
}
|
||||
}
|
||||
|
||||
ap_awake = 1;
|
||||
ap_spin = 0;
|
||||
ia64_ap_state.as_awake = 1;
|
||||
ia64_ap_state.as_spin = 0;
|
||||
|
||||
while (ap_awake != smp_cpus)
|
||||
while (ia64_ap_state.as_awake != smp_cpus)
|
||||
cpu_spinwait();
|
||||
|
||||
if (smp_cpus != cpus || cpus != mp_ncpus) {
|
||||
@ -432,21 +493,19 @@ ipi_all_but_self(int ipi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an IPI to the specified processor. The lid parameter holds the
|
||||
* cr.lid (CR64) contents of the target processor. Only the id and eid
|
||||
* fields are used here.
|
||||
* Send an IPI to the specified processor.
|
||||
*/
|
||||
void
|
||||
ipi_send(struct pcpu *cpu, int xiv)
|
||||
{
|
||||
u_int lid;
|
||||
u_int sapic_id;
|
||||
|
||||
KASSERT(xiv != 0, ("ipi_send"));
|
||||
|
||||
lid = LID_SAPIC(cpu->pc_md.lid);
|
||||
sapic_id = IA64_LID_GET_SAPIC_ID(cpu->pc_md.lid);
|
||||
|
||||
ia64_mf();
|
||||
ia64_st8(&(ia64_pib->ib_ipi[lid][0]), xiv);
|
||||
ia64_st8(&(ia64_pib->ib_ipi[sapic_id][0]), xiv);
|
||||
ia64_mf_a();
|
||||
CTR3(KTR_SMP, "ipi_send(%p, %d): cpuid=%d", cpu, xiv, PCPU_GET(cpuid));
|
||||
}
|
||||
|
@ -159,7 +159,8 @@ vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
|
||||
* Kernel virtual memory management.
|
||||
*/
|
||||
static int nkpt;
|
||||
struct ia64_lpte ***ia64_kptdir;
|
||||
extern struct ia64_lpte ***ia64_kptdir;
|
||||
|
||||
#define KPTE_DIR0_INDEX(va) \
|
||||
(((va) >> (3*PAGE_SHIFT-8)) & ((1<<(PAGE_SHIFT-3))-1))
|
||||
#define KPTE_DIR1_INDEX(va) \
|
||||
@ -177,7 +178,7 @@ static uint64_t pmap_ptc_e_count2 = 2;
|
||||
static uint64_t pmap_ptc_e_stride1 = 0x2000;
|
||||
static uint64_t pmap_ptc_e_stride2 = 0x100000000;
|
||||
|
||||
volatile u_long pmap_ptc_g_sem;
|
||||
extern volatile u_long pmap_ptc_g_sem;
|
||||
|
||||
/*
|
||||
* Data for the RID allocator
|
||||
@ -390,13 +391,18 @@ pmap_bootstrap()
|
||||
;
|
||||
count = i+2;
|
||||
|
||||
/*
|
||||
* Determine a valid (mappable) VHPT size.
|
||||
*/
|
||||
TUNABLE_INT_FETCH("machdep.vhpt.log2size", &pmap_vhpt_log2size);
|
||||
if (pmap_vhpt_log2size == 0)
|
||||
pmap_vhpt_log2size = 20;
|
||||
else if (pmap_vhpt_log2size < 15)
|
||||
pmap_vhpt_log2size = 15;
|
||||
else if (pmap_vhpt_log2size > 61)
|
||||
pmap_vhpt_log2size = 61;
|
||||
else if (pmap_vhpt_log2size < 16)
|
||||
pmap_vhpt_log2size = 16;
|
||||
else if (pmap_vhpt_log2size > 28)
|
||||
pmap_vhpt_log2size = 28;
|
||||
if (pmap_vhpt_log2size & 1)
|
||||
pmap_vhpt_log2size--;
|
||||
|
||||
base = 0;
|
||||
size = 1UL << pmap_vhpt_log2size;
|
||||
@ -453,16 +459,6 @@ pmap_bootstrap()
|
||||
/* Region 5 is mapped via the VHPT. */
|
||||
ia64_set_rr(IA64_RR_BASE(5), (5 << 8) | (PAGE_SHIFT << 2) | 1);
|
||||
|
||||
/*
|
||||
* Region 6 is direct mapped UC and region 7 is direct mapped
|
||||
* WC. The details of this is controlled by the Alt {I,D}TLB
|
||||
* handlers. Here we just make sure that they have the largest
|
||||
* possible page size to minimise TLB usage.
|
||||
*/
|
||||
ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (IA64_ID_PAGE_SHIFT << 2));
|
||||
ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (IA64_ID_PAGE_SHIFT << 2));
|
||||
ia64_srlz_d();
|
||||
|
||||
/*
|
||||
* Clear out any random TLB entries left over from booting.
|
||||
*/
|
||||
@ -1210,7 +1206,6 @@ vm_paddr_t
|
||||
pmap_kextract(vm_offset_t va)
|
||||
{
|
||||
struct ia64_lpte *pte;
|
||||
vm_offset_t gwpage;
|
||||
|
||||
KASSERT(va >= VM_MAXUSER_ADDRESS, ("Must be kernel VA"));
|
||||
|
||||
@ -1218,19 +1213,16 @@ pmap_kextract(vm_offset_t va)
|
||||
if (va >= IA64_RR_BASE(6))
|
||||
return (IA64_RR_MASK(va));
|
||||
|
||||
/* EPC gateway page? */
|
||||
gwpage = (vm_offset_t)ia64_get_k5();
|
||||
if (va >= gwpage && va < gwpage + PAGE_SIZE)
|
||||
return (IA64_RR_MASK((vm_offset_t)ia64_gateway_page));
|
||||
|
||||
/* Bail out if the virtual address is beyond our limits. */
|
||||
if (va >= kernel_vm_end)
|
||||
return (0);
|
||||
|
||||
pte = pmap_find_kpte(va);
|
||||
if (!pmap_present(pte))
|
||||
return (0);
|
||||
return (pmap_ppn(pte) | (va & PAGE_MASK));
|
||||
if (va >= VM_MIN_KERNEL_ADDRESS) {
|
||||
pte = pmap_find_kpte(va);
|
||||
return (pmap_present(pte) ? pmap_ppn(pte)|(va&PAGE_MASK) : 0);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -101,10 +101,6 @@ ia64_sal_init(void)
|
||||
}
|
||||
case 5: {
|
||||
struct sal_ap_wakeup_descriptor *dp;
|
||||
#ifdef SMP
|
||||
struct ia64_sal_result result;
|
||||
struct ia64_fdesc *fd;
|
||||
#endif
|
||||
|
||||
dp = (struct sal_ap_wakeup_descriptor*)p;
|
||||
if (dp->sale_mechanism != 0) {
|
||||
@ -126,14 +122,6 @@ ia64_sal_init(void)
|
||||
if (bootverbose)
|
||||
printf("SAL: AP wake-up XIV: %#x\n",
|
||||
ia64_ipi_wakeup);
|
||||
|
||||
#ifdef SMP
|
||||
fd = (struct ia64_fdesc *) os_boot_rendez;
|
||||
result = ia64_sal_entry(SAL_SET_VECTORS,
|
||||
SAL_OS_BOOT_RENDEZ, ia64_tpa(fd->func),
|
||||
ia64_tpa(fd->gp), 0, 0, 0, 0);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,12 @@
|
||||
#ifndef _MACHINE_IA64_CPU_H_
|
||||
#define _MACHINE_IA64_CPU_H_
|
||||
|
||||
/*
|
||||
* Local Interrupt ID.
|
||||
*/
|
||||
#define IA64_LID_GET_SAPIC_ID(x) ((u_int)((x) >> 16) & 0xffff)
|
||||
#define IA64_LID_SET_SAPIC_ID(x) ((u_int)((x) & 0xffff) << 16)
|
||||
|
||||
/*
|
||||
* Definition of DCR bits.
|
||||
*/
|
||||
|
@ -16,6 +16,24 @@
|
||||
|
||||
struct pcpu;
|
||||
|
||||
struct ia64_ap_state {
|
||||
uint64_t as_trace;
|
||||
uint64_t as_pgtbl_pte;
|
||||
uint64_t as_pgtbl_itir;
|
||||
uint64_t as_text_va;
|
||||
uint64_t as_text_pte;
|
||||
uint64_t as_text_itir;
|
||||
uint64_t as_data_va;
|
||||
uint64_t as_data_pte;
|
||||
uint64_t as_data_itir;
|
||||
void *as_kstack;
|
||||
void *as_kstack_top;
|
||||
struct pcpu *as_pcpu;
|
||||
volatile int as_delay;
|
||||
volatile u_int as_awake;
|
||||
volatile u_int as_spin;
|
||||
};
|
||||
|
||||
extern int ia64_ipi_ast;
|
||||
extern int ia64_ipi_highfp;
|
||||
extern int ia64_ipi_nmi;
|
||||
|
@ -124,8 +124,8 @@
|
||||
#define IA64_RR_BASE(n) (((uint64_t) (n)) << 61)
|
||||
#define IA64_RR_MASK(x) ((x) & ((1L << 61) - 1))
|
||||
|
||||
#define IA64_PHYS_TO_RR6(x) ((x) | IA64_RR_BASE(6))
|
||||
#define IA64_PHYS_TO_RR7(x) ((x) | IA64_RR_BASE(7))
|
||||
#define IA64_PHYS_TO_RR6(x) ((x) | IA64_RR_BASE(6))
|
||||
#define IA64_PHYS_TO_RR7(x) ((x) | IA64_RR_BASE(7))
|
||||
|
||||
/*
|
||||
* The Itanium architecture defines that all implementations support at
|
||||
@ -138,18 +138,6 @@
|
||||
#define IA64_REGION_GAP_START 0x0004000000000000
|
||||
#define IA64_REGION_GAP_EXTEND 0x1ffc000000000000
|
||||
|
||||
/*
|
||||
* Page size of the identity mappings in region 7.
|
||||
*/
|
||||
#ifndef LOG2_ID_PAGE_SIZE
|
||||
#define LOG2_ID_PAGE_SIZE 28 /* 256M */
|
||||
#endif
|
||||
|
||||
#define IA64_ID_PAGE_SHIFT (LOG2_ID_PAGE_SIZE)
|
||||
#define IA64_ID_PAGE_SIZE (1<<(LOG2_ID_PAGE_SIZE))
|
||||
#define IA64_ID_PAGE_MASK (IA64_ID_PAGE_SIZE-1)
|
||||
|
||||
|
||||
/*
|
||||
* Parameters for Pre-Boot Virtual Memory (PBVM).
|
||||
* The kernel, its modules and metadata are loaded in the PBVM by the loader.
|
||||
|
Loading…
Reference in New Issue
Block a user