Page MenuHomeFreeBSD

D14768.id40495.diff
No OneTemporary

D14768.id40495.diff

Index: sys/amd64/amd64/db_interface.c
===================================================================
--- sys/amd64/amd64/db_interface.c
+++ sys/amd64/amd64/db_interface.c
@@ -37,6 +37,7 @@
#include <sys/pcpu.h>
#include <machine/cpufunc.h>
+#include <machine/md_var.h>
#include <machine/specialreg.h>
#include <ddb/ddb.h>
@@ -75,19 +76,19 @@
jmp_buf jb;
void *prev_jb;
char *dst;
- u_long cr0save;
+ bool old_wp;
int ret;
- cr0save = rcr0();
+ old_wp = false;
prev_jb = kdb_jmpbuf(jb);
ret = setjmp(jb);
if (ret == 0) {
- load_cr0(cr0save & ~CR0_WP);
+ old_wp = disable_wp();
dst = (char *)addr;
while (size-- > 0)
*dst++ = *data++;
}
- load_cr0(cr0save);
+ restore_wp(old_wp);
(void)kdb_jmpbuf(prev_jb);
return (ret);
}
Index: sys/amd64/amd64/fpu.c
===================================================================
--- sys/amd64/amd64/fpu.c
+++ sys/amd64/amd64/fpu.c
@@ -205,6 +205,7 @@
{
u_int cp[4];
uint64_t xsave_mask_user;
+ bool old_wp;
if ((cpu_feature2 & CPUID2_XSAVE) != 0) {
use_xsave = 1;
@@ -233,8 +234,14 @@
* Patch the XSAVE instruction in the cpu_switch code
* to XSAVEOPT. We assume that XSAVE encoding used
* REX byte, and set the bit 4 of the r/m byte.
+ *
+ * It seems that some BIOSes give control to the OS
+ * with CR0.WP already set, making the kernel text
+ * read-only before cpu_startup().
*/
+ old_wp = disable_wp();
ctx_switch_xsave[3] |= 0x10;
+ restore_wp(old_wp);
}
}
Index: sys/amd64/amd64/gdb_machdep.c
===================================================================
--- sys/amd64/amd64/gdb_machdep.c
+++ sys/amd64/amd64/gdb_machdep.c
@@ -39,6 +39,7 @@
#include <machine/cpufunc.h>
#include <machine/frame.h>
#include <machine/gdb_machdep.h>
+#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/psl.h>
#include <machine/reg.h>
@@ -127,17 +128,14 @@
void *
gdb_begin_write(void)
{
- u_long cr0save;
- cr0save = rcr0();
- load_cr0(cr0save & ~CR0_WP);
- return ((void *)cr0save);
+ return (disable_wp() ? &gdb_begin_write : NULL);
}
void
gdb_end_write(void *arg)
{
- load_cr0((u_long)arg);
+ restore_wp(arg != NULL);
}
Index: sys/amd64/amd64/machdep.c
===================================================================
--- sys/amd64/amd64/machdep.c
+++ sys/amd64/amd64/machdep.c
@@ -1554,6 +1554,12 @@
TSRAW(&thread0, TS_ENTER, __func__, NULL);
+ /*
+ * Enable write to the kernel text and read-only data segment
+ * for early boot fixups.
+ */
+ (void)disable_wp();
+
/*
* This may be done better later if it gets more high level
* components in it. If so just link td->td_proc here.
@@ -2597,6 +2603,31 @@
: "cc", "memory");
}
+/*
+ * Enable and restore kernel text write permissions.
+ * Callers must ensure that disable_wp()/restore_wp() are executed
+ * without rescheduling on the same core.
+ */
+bool
+disable_wp(void)
+{
+ u_int cr0;
+
+ cr0 = rcr0();
+ if ((cr0 & CR0_WP) == 0)
+ return (false);
+ load_cr0(cr0 & ~CR0_WP);
+ return (true);
+}
+
+void
+restore_wp(bool old_wp)
+{
+
+ if (old_wp)
+ load_cr0(rcr0() | CR0_WP);
+}
+
#ifdef KDB
/*
Index: sys/amd64/include/md_var.h
===================================================================
--- sys/amd64/include/md_var.h
+++ sys/amd64/include/md_var.h
@@ -53,6 +53,8 @@
void amd64_db_resume_dbreg(void);
void amd64_lower_shared_page(struct sysentvec *);
void amd64_syscall(struct thread *td, int traced);
+bool disable_wp(void);
+void restore_wp(bool old_wp);
void doreti_iret(void) __asm(__STRING(doreti_iret));
void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault));
void ld_ds(void) __asm(__STRING(ld_ds));

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 31, 10:47 PM (2 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28207966
Default Alt Text
D14768.id40495.diff (3 KB)

Event Timeline