Skip site navigation (1)Skip section navigation (2)
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>