Date: Wed, 29 Sep 2010 13:22:56 -0700 From: Matthew Fleming <mdf356@gmail.com> To: Kostik Belousov <kostikbel@gmail.com> Cc: freebsd-hackers@freebsd.org Subject: Re: Adding a V=R mapping for amd64? Message-ID: <AANLkTikqoET_t%2B6V4_3YxNd-WWuSH7imgJuVodXPqnQU@mail.gmail.com> In-Reply-To: <20100929201221.GG43070@deviant.kiev.zoral.com.ua> References: <AANLkTinUCXES2UhLHPQD7YCjt5Sx4X5%2BgERJZNjsR-ho@mail.gmail.com> <20100929201221.GG43070@deviant.kiev.zoral.com.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Sep 29, 2010 at 1:12 PM, Kostik Belousov <kostikbel@gmail.com> wrot= e: > On Wed, Sep 29, 2010 at 12:40:57PM -0700, Matthew Fleming wrote: >> I'm hacking around with making a "fast reboot" that puts a copy of the >> MBR from disk into address 0x7c00 and, after disabling various >> translation bits and stopping other CPUs, branches to it, to skip the >> hardware self test that normally happens on boot. >> >> I haven't gotten to the point of attempting to run the code at 0x7c00 >> because I'm first hitting a different error. =A0Despite my attempts to >> enter a translation into the hardware page table, I get a panic trying >> to write to address 0x7000, where I intended to put the trampoline >> code that turns off translation. >> >> Rebooting... >> Attempt to reset to MBR... >> XXX attempting pmap_kenter()... >> XXX copying bootstrap code... >> panic @ time 1285760103.939, thread 0xffffff000775d960: Fatal trap 12: >> page fault while in kernel mode >> >> cpuid =3D 0 >> Panic occurred in module kernel loaded at 0xffffffff80100000: >> >> Stack: -------------------------------------------------- >> kernel:trap_fatal+0xac >> kernel:trap_pfault+0x24c >> kernel:trap+0x42e >> kernel:bcopy+0x16 >> kernel:shutdown_reset+0x48 >> kernel:boot+0x317 >> kernel:reboot+0x60 >> kernel:ia32_syscall+0x1cd >> -------------------------------------------------- >> cpuid =3D 0; apic id =3D 00 >> fault virtual address =A0 =3D 0x7000 >> fault code =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D supervisor write data, page no= t present >> stack pointer =A0 =A0 =A0 =A0 =A0 =3D 0x10:0xffffff8059e07670 >> frame pointer =A0 =A0 =A0 =A0 =A0 =3D 0x10:0xffffff8059e07780 >> >> Here's what I think is the relevant snippets of code. =A0Note that I >> reserved the vm_page_t for physical page 7 as mbr_page early in boot, >> so I know the memory is free. >> >> void >> pmap_kenter_VR(vm_paddr_t pa) >> { >> =A0 =A0 =A0 pmap_t pmap =3D kernel_pmap; >> =A0 =A0 =A0 vm_page_t mpte; >> =A0 =A0 =A0 pd_entry_t *pde; >> =A0 =A0 =A0 pt_entry_t *pte; >> >> =A0 =A0 =A0 vm_page_lock_queues(); >> =A0 =A0 =A0 PMAP_LOCK(pmap); >> =A0 =A0 =A0 mpte =3D pmap_allocpte(pmap, pa, M_WAITOK); >> >> =A0 =A0 =A0 pde =3D pmap_pde(pmap, pa); >> =A0 =A0 =A0 if (pde =3D=3D NULL || (*pde & PG_V) =3D=3D 0) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 panic("%s: invalid page directory va=3D%#lx"= , __func__, pa); >> =A0 =A0 =A0 if ((*pde & PG_PS) !=3D 0) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 panic("%s: attempted pmap_enter on 2MB page"= , __func__); >> =A0 =A0 =A0 pte =3D pmap_pde_to_pte(pde, pa); >> =A0 =A0 =A0 if (pte =3D=3D NULL) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 panic("%s: no pte va=3D%#lx", __func__, pa); >> >> =A0 =A0 =A0 if (*pte !=3D 0) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Remove extra pte reference. */ >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpte->wire_count--; >> =A0 =A0 =A0 } >> =A0 =A0 =A0 =A0 pte_store(pte, pa | PG_RW | PG_V | PG_G | pg_nx); >> >> =A0 =A0 =A0 vm_page_unlock_queues(); >> =A0 =A0 =A0 PMAP_UNLOCK(pmap); >> } >> >> Then in cpu_reset(): >> >> =A0 =A0 =A0 /* >> =A0 =A0 =A0 =A0* Establish a V=3DR mapping for the MBR page, and copy a >> =A0 =A0 =A0 =A0* reasonable guess at the size of the bootstrap code into= the >> =A0 =A0 =A0 =A0* beginning of the page. >> =A0 =A0 =A0 =A0*/ >> =A0 =A0 =A0 printf("XXX attempting pmap_kenter()...\n"); >> =A0 =A0 =A0 pmap_kenter_VR(trunc_page(mbaddr)); >> =A0 =A0 =A0 printf("XXX copying bootstrap code...\n"); >> =A0 =A0 =A0 to_copy =3D (uintptr_t)xxx_reset_end - (uintptr_t)xxx_reset_= real; >> =A0 =A0 =A0 if (to_copy > mbaddr - trunc_page(mbaddr)) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 to_copy =3D mbaddr - trunc_page(mbaddr); >> =A0 =A0 =A0 bcopy(xxx_reset_real, (void *)trunc_page(mbaddr), to_copy); = =A0/* die here */ >> =A0 =A0 =A0 printf("XXX attempting to turn off xlation and re-run MBR...= \n"); >> =A0 =A0 =A0 xxx_reset_real(mbaddr); >> >> >> My first attempt was a call to >> =A0 =A0 =A0 pmap_kenter(trunc_page(0x7c00), trunc_page(0x7c00)); >> which failed trying to dereference the non-existent PDE. >> >> My second attempt called >> =A0 =A0 =A0 pmap_enter(kernel_pmap, trunc_page(0x7c00), VM_PROT_WRITE, m= br_page, >> =A0 =A0 =A0 =A0 =A0 VM_PROT_ALL, 0); >> That failed with the same crash as the attempt using pmap_kenter_VR(). >> >> So... any thoughts as to why, after an apparently successful >> installation of an xlation, I still get a panic as though there were >> no xlation? > > Weird formatting of backtrace. Is this some proprietary code ? Yeah, there's some Isilon local modifications. > Why do you try to create 1-1 mapping at all ? The MBR code should be > executing in real mode anyway, and the mapping address at the moment of > bcopy does not matter at all. I think that the use of PHYS_TO_DMAP() > should give you direct mapping. I assumed I need trampoline code. The moment I turn off the xlation bits, if the instruction pointer I'm running from is the normal kernel addresses, won't I die horribly trying to access 0xffffffff80000000 or so in real mode? > About the #pf that you see. I think that this is due to the fact that > you are modifying kernel pmap, while the active one is the pmap of > the user process which context issued reboot(). Isn't the kernel pmap active in the kernel, since I've entered via the syscall reboot(2) ? Thanks, matthew
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTikqoET_t%2B6V4_3YxNd-WWuSH7imgJuVodXPqnQU>