Rainer Hurling wrote:
Am 29.08.18 um 16:12 schrieb Kyle Evans:
On Wed, Aug 29, 2018 at 6:53 AM Yuri Pankov <yur...@yuripv.net> wrote:
Yuri Pankov wrote:
Konstantin Belousov wrote:
On Wed, Aug 29, 2018 at 12:37:52PM +0300, Yuri Pankov wrote:
Hi,
I've noticed that all recent snapshots (ALPHA3, ALPHA2, ALPHA1,
20180802) fail to boot on MBP 2017:
kbd0 at kbdmux0
netmap: loaded module
nexus0
Fatal trap 12: page fault while in kernel mode
cpuid = 2: apic id = 02
fault virtual address = 0x74c64a50
fault code = supervisor read data, page not present
instruction pointer = 0x20: 0x7abece31
stack pointer = 0x28: 0xffffffff82b2f7c0
frame pointer = 0x28: 0xffffffff82b2f810
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 0 (swapper)
[ thread pid 0 tid 100000 ]
Stopped at 0x7abece31: calll *0x18(%rax)
db>
Sadly, there's no support for internal keyboard yet (it's connected via
SPI), and external USB one stops working.
A (not so quick) bisect is pointing at r336921, which enabled EFIRT.
Some questions here:
- is this something that can/should be fixed?
- can we print some "enabling EFIRT" message to the console to make
guesses about the problem source a bit easier?
It is not in 'enabling'. Looking at the faulting VA, I believe that
it occurs inside the BIOS code.
Disable efirt by removing the kernel option, then try to load the module
at runtime. Does it still fault ? Also, get the efi mem map for the
machine and look at which region the faulting address and the faulting
instruction belong.
kldload'ing the efirt module gets the same fault. Several top lines of
backtrace:
kernphys() at 0x7abece31
efi_get_time() at efi_get_time+0xd9
efirtc_probe() at efirtc_probe+0x17
For the efi mem map, if I'm understanding it correctly, there's the
following:
...
BootServicesData 00007421d000 000000000000 00000a8b UC WC WT WB
...
RuntimeServicesCode 00007ab9f000 000000000000 00000070 UC WC WT WB
...
Hi,
I guess this patch might do it:
https://people.freebsd.org/~kevans/efi-bootmap.diff
Linux commit messages depict a tale in which they used to also only
map RUNTIME entries, but they were effectively forced to back down on
that because of buggy firmware that does exactly what you've described
and they later reintroduced the restrictive mapping for i386-only
where they'd not found such bugs.
Thanks,
Kyle Evans
Hi Kyle,
After Yuri had no success with the patches of kib, I tried your patch on
a DELL Latitude E6520 with BIOS version A21.
Sorry, I accidentally took the discussion off-list, where Konstantin
provided some more patches. I'm attaching the one that finally worked
for me. It also adds some diagnostic prints which require bootverbose
to be enabled.
diff --git a/sys/amd64/amd64/efirt_machdep.c b/sys/amd64/amd64/efirt_machdep.c
index da7783043a2..80ffa66f5ec 100644
--- a/sys/amd64/amd64/efirt_machdep.c
+++ b/sys/amd64/amd64/efirt_machdep.c
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <machine/vmparam.h>
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <vm/vm_extern.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
@@ -266,6 +267,7 @@ efi_arch_enter(void)
curpmap = PCPU_GET(curpmap);
PMAP_LOCK_ASSERT(curpmap, MA_OWNED);
+ curthread->td_md.md_efirt_dis_pf = vm_fault_disable_pagefaults();
/*
* IPI TLB shootdown handler invltlb_pcid_handler() reloads
@@ -300,6 +302,7 @@ efi_arch_leave(void)
curpmap->pm_pcids[PCPU_GET(cpuid)].pm_pcid : 0));
if (!pmap_pcid_enabled)
invltlb();
+ vm_fault_enable_pagefaults(curthread->td_md.md_efirt_dis_pf);
}
/* XXX debug stuff */
diff --git a/sys/amd64/amd64/efirt_support.S b/sys/amd64/amd64/efirt_support.S
new file mode 100644
index 00000000000..82e5646e645
--- /dev/null
+++ b/sys/amd64/amd64/efirt_support.S
@@ -0,0 +1,105 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Konstantin Belousov <k...@freebsd.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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/asmacros.h>
+
+#include "assym.inc"
+
+ .text
+ENTRY(efirt_arch_call)
+ pushq %rbp
+ movq %rsp, %rbp
+
+ movq %rbx, EC_STATE+TF_RBX(%rdi)
+ movq %rsp, EC_STATE+TF_RSP(%rdi)
+ movq %rbp, EC_STATE+TF_RBP(%rdi)
+ movq %r12, EC_STATE+TF_R12(%rdi)
+ movq %r13, EC_STATE+TF_R13(%rdi)
+ movq %r14, EC_STATE+TF_R14(%rdi)
+ movq %r15, EC_STATE+TF_R15(%rdi)
+ movq PCPU(CURTHREAD), %rax
+ movq %rdi, TD_MD+MD_EFIRT_TMP(%rax)
+
+ movq PCPU(CURPCB), %rsi
+ movq $efirt_fault, PCB_ONFAULT(%rsi)
+
+ movl EC_ARGCNT(%rdi), %ecx
+ movl %ecx, %ebx
+ shll $3, %ecx
+ subq %rcx, %rsp
+
+ cmpl $0, %ebx
+ jz 1f
+ movq EC_ARG1(%rdi), %rcx
+ decl %ebx
+ jz 1f
+ movq EC_ARG2(%rdi), %rdx
+ decl %ebx
+ jz 1f
+ movq EC_ARG3(%rdi), %r8
+ decl %ebx
+ jz 1f
+ movq EC_ARG4(%rdi), %r9
+ /* XXX on-stack regs */
+1: movq EC_FPTR(%rdi), %rax
+ callq *%rax
+
+ movq PCPU(CURTHREAD), %rbx
+ movq TD_MD+MD_EFIRT_TMP(%rbx), %rdi
+ movq %rax, EC_STATE(%rdi)
+ movq PCPU(CURPCB), %rsi
+ xorl %eax, %eax
+ movq %rax, PCB_ONFAULT(%rsi)
+
+efirt_arch_call_tail:
+ movq EC_STATE+TF_R15(%rdi), %r15
+ movq EC_STATE+TF_R14(%rdi), %r14
+ movq EC_STATE+TF_R13(%rdi), %r13
+ movq EC_STATE+TF_R12(%rdi), %r12
+ movq EC_STATE+TF_RBP(%rdi), %rbp
+ movq EC_STATE+TF_RSP(%rdi), %rsp
+ movq EC_STATE+TF_RBX(%rdi), %rbx
+
+ popq %rbp
+ ret
+END(efirt_arch_call)
+
+ENTRY(efirt_fault)
+ xorl %eax, %eax
+ movq PCPU(CURPCB), %rsi
+ movq %rax, PCB_ONFAULT(%rsi)
+ movl $EFAULT, %eax
+ movq PCPU(CURTHREAD), %rbx
+ movq TD_MD+MD_EFIRT_TMP(%rbx), %rdi
+ jmp efirt_arch_call_tail
+END(efirt_fault)
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index d61b5c7bb6d..c38a596089a 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -77,12 +77,15 @@ ASSYM(P_MD, offsetof(struct proc, p_md));
ASSYM(MD_LDT, offsetof(struct mdproc, md_ldt));
ASSYM(MD_LDT_SD, offsetof(struct mdproc, md_ldt_sd));
+ASSYM(MD_EFIRT_TMP, offsetof(struct mdthread, md_efirt_tmp));
+
ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
ASSYM(TD_PFLAGS, offsetof(struct thread, td_pflags));
ASSYM(TD_PROC, offsetof(struct thread, td_proc));
ASSYM(TD_FRAME, offsetof(struct thread, td_frame));
+ASSYM(TD_MD, offsetof(struct thread, td_md));
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
@@ -249,3 +252,12 @@ ASSYM(__FreeBSD_version, __FreeBSD_version);
#ifdef HWPMC_HOOKS
ASSYM(PMC_FN_USER_CALLCHAIN, PMC_FN_USER_CALLCHAIN);
#endif
+
+ASSYM(EC_EFI_STATUS, offsetof(struct efirt_callinfo, ec_efi_status));
+ASSYM(EC_FPTR, offsetof(struct efirt_callinfo, ec_fptr));
+ASSYM(EC_ARGCNT, offsetof(struct efirt_callinfo, ec_argcnt));
+ASSYM(EC_ARG1, offsetof(struct efirt_callinfo, ec_arg1));
+ASSYM(EC_ARG2, offsetof(struct efirt_callinfo, ec_arg2));
+ASSYM(EC_ARG3, offsetof(struct efirt_callinfo, ec_arg3));
+ASSYM(EC_ARG4, offsetof(struct efirt_callinfo, ec_arg4));
+ASSYM(EC_STATE, offsetof(struct efirt_callinfo, ec_state));
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 019decb837a..4d03da234f1 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -806,7 +806,7 @@ trap_pfault(struct trapframe *frame, int usermode)
* If nx protection of the usermode portion of kernel page
* tables caused trap, panic.
*/
- if (PCPU_GET(curpmap)->pm_ucr3 != PMAP_NO_CR3 && usermode &&
+ if (usermode && PCPU_GET(curpmap)->pm_ucr3 != PMAP_NO_CR3 &&
pg_nx != 0 && (frame->tf_err & (PGEX_P | PGEX_W |
PGEX_U | PGEX_I)) == (PGEX_P | PGEX_U | PGEX_I) &&
(curpcb->pcb_saved_ucr3 & ~CR3_PCID_MASK)==
diff --git a/sys/amd64/include/frame.h b/sys/amd64/include/frame.h
index f0a6fcf5bc9..c84ee2a2064 100644
--- a/sys/amd64/include/frame.h
+++ b/sys/amd64/include/frame.h
@@ -47,4 +47,15 @@ struct pti_frame {
register_t pti_ss;
};
+struct efirt_callinfo {
+ register_t ec_efi_status;
+ register_t ec_fptr;
+ register_t ec_argcnt;
+ register_t ec_arg1;
+ register_t ec_arg2;
+ register_t ec_arg3;
+ register_t ec_arg4;
+ struct trapframe ec_state;
+};
+
#endif
diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h
index f52c71208e6..54f5b416a7d 100644
--- a/sys/amd64/include/proc.h
+++ b/sys/amd64/include/proc.h
@@ -62,6 +62,8 @@ struct mdthread {
register_t md_saved_flags; /* (k) */
register_t md_spurflt_addr; /* (k) Spurious page fault address. */
struct pmap_invl_gen md_invl_gen;
+ register_t md_efirt_tmp; /* (k) */
+ int md_efirt_dis_pf; /* (k) */
};
struct mdproc {
diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c
index d48074d72d6..088c80cfb71 100644
--- a/sys/dev/efidev/efirt.c
+++ b/sys/dev/efidev/efirt.c
@@ -96,6 +96,8 @@ static int efi_status2err[25] = {
static int efi_enter(void);
static void efi_leave(void);
+int efirt_arch_call(struct efirt_callinfo *);
+
static int
efi_status_to_errno(efi_status status)
{
@@ -296,16 +298,22 @@ efi_get_table(struct uuid *uuid, void **ptr)
static int
efi_get_time_locked(struct efi_tm *tm, struct efi_tmcap *tmcap)
{
- efi_status status;
+ struct efirt_callinfo ec;
int error;
EFI_TIME_OWNED()
+ bzero(&ec, sizeof(ec));
+ ec.ec_argcnt = 2;
+ ec.ec_arg1 = (uintptr_t)tm;
+ ec.ec_arg2 = (uintptr_t)tmcap;
error = efi_enter();
if (error != 0)
return (error);
- status = efi_runtime->rt_gettime(tm, tmcap);
+ ec.ec_fptr = (uintptr_t)(efi_runtime->rt_gettime);
+ error = efirt_arch_call(&ec);
efi_leave();
- error = efi_status_to_errno(status);
+ if (error == 0)
+ error = efi_status_to_errno(ec.ec_efi_status);
return (error);
}
@@ -359,16 +367,21 @@ efi_reset_system(void)
static int
efi_set_time_locked(struct efi_tm *tm)
{
- efi_status status;
+ struct efirt_callinfo ec;
int error;
EFI_TIME_OWNED();
+ bzero(&ec, sizeof(ec));
+ ec.ec_argcnt = 1;
+ ec.ec_arg1 = (uintptr_t)tm;
error = efi_enter();
if (error != 0)
return (error);
- status = efi_runtime->rt_settime(tm);
+ ec.ec_fptr = (uintptr_t)(efi_runtime->rt_settime);
+ error = efirt_arch_call(&ec);
efi_leave();
- error = efi_status_to_errno(status);
+ if (error == 0)
+ error = efi_status_to_errno(ec.ec_efi_status);
return (error);
}
diff --git a/sys/dev/efidev/efirtc.c b/sys/dev/efidev/efirtc.c
index b9e06bcc362..e5a2ec262bf 100644
--- a/sys/dev/efidev/efirtc.c
+++ b/sys/dev/efidev/efirtc.c
@@ -74,7 +74,8 @@ efirtc_probe(device_t dev)
*/
if ((error = efi_get_time(&tm)) != 0) {
if (bootverbose)
- device_printf(dev, "cannot read EFI realtime clock\n");
+ device_printf(dev, "cannot read EFI realtime clock, "
+ "error %d\n", error);
return (error);
}
device_set_desc(dev, "EFI Realtime Clock");
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 79b34dc7649..b60c2d5b40e 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -83,7 +83,7 @@ _Static_assert(offsetof(struct thread, td_pflags) == 0x104,
"struct thread KBI td_pflags");
_Static_assert(offsetof(struct thread, td_frame) == 0x470,
"struct thread KBI td_frame");
-_Static_assert(offsetof(struct thread, td_emuldata) == 0x518,
+_Static_assert(offsetof(struct thread, td_emuldata) == 0x528,
"struct thread KBI td_emuldata");
_Static_assert(offsetof(struct proc, p_flag) == 0xb0,
"struct proc KBI p_flag");
diff --git a/sys/kern/subr_rtc.c b/sys/kern/subr_rtc.c
index 82c276f210a..1c3a9804694 100644
--- a/sys/kern/subr_rtc.c
+++ b/sys/kern/subr_rtc.c
@@ -138,6 +138,7 @@ settime_task_func(void *arg, int pending)
{
struct timespec ts;
struct rtc_instance *rtc;
+ int error;
rtc = arg;
if (!(rtc->flags & CLOCKF_SETTIME_NO_TS)) {
@@ -150,7 +151,9 @@ settime_task_func(void *arg, int pending)
ts.tv_sec = 0;
ts.tv_nsec = 0;
}
- CLOCK_SETTIME(rtc->clockdev, &ts);
+ error = CLOCK_SETTIME(rtc->clockdev, &ts);
+ if (error != 0 && bootverbose)
+ device_printf(rtc->clockdev, "CLOCK_SETTIME error %d\n", error);
}
static void
diff --git a/sys/modules/efirt/Makefile b/sys/modules/efirt/Makefile
index 2613150db48..524d93ead93 100644
--- a/sys/modules/efirt/Makefile
+++ b/sys/modules/efirt/Makefile
@@ -5,7 +5,11 @@
KMOD= efirt
SRCS= efirt.c efirt_machdep.c efidev.c
-SRCS+= efirtc.c
+SRCS+= efirtc.c efirt_support.S
SRCS+= device_if.h bus_if.h clock_if.h
+efirt_support.o: efirt_support.S assym.inc
+ ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
+ ${.IMPSRC} -o ${.TARGET}
+
.include <bsd.kmod.mk>
_______________________________________________
freebsd-current@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"