Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Mar 2018 17:43:50 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r331252 - in head/sys/amd64: amd64 include
Message-ID:  <201803201743.w2KHhoF9055658@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Tue Mar 20 17:43:50 2018
New Revision: 331252
URL: https://svnweb.freebsd.org/changeset/base/331252

Log:
  Provide KPI for handling of rw/ro kernel text.
  
  This is a pure syntax patch to create an interface to enable and later
  restore write access to the kernel text and other read-only mapped
  regions.  It is in line with e.g. vm_fault_disable_pagefaults() by
  allowing the nesting.
  
  Discussed with:	Peter Lei <peter.lei@ieee.org>
  Reviewed by:	jtl
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week
  Differential revision:	https://reviews.freebsd.org/D14768

Modified:
  head/sys/amd64/amd64/db_interface.c
  head/sys/amd64/amd64/gdb_machdep.c
  head/sys/amd64/amd64/machdep.c
  head/sys/amd64/include/md_var.h

Modified: head/sys/amd64/amd64/db_interface.c
==============================================================================
--- head/sys/amd64/amd64/db_interface.c	Tue Mar 20 17:41:54 2018	(r331251)
+++ head/sys/amd64/amd64/db_interface.c	Tue Mar 20 17:43:50 2018	(r331252)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #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 @@ db_write_bytes(vm_offset_t addr, size_t size, char *da
 	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);
 }

Modified: head/sys/amd64/amd64/gdb_machdep.c
==============================================================================
--- head/sys/amd64/amd64/gdb_machdep.c	Tue Mar 20 17:41:54 2018	(r331251)
+++ head/sys/amd64/amd64/gdb_machdep.c	Tue Mar 20 17:43:50 2018	(r331252)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #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 @@ gdb_cpu_signal(int type, int code)
 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);
 }
 

Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c	Tue Mar 20 17:41:54 2018	(r331251)
+++ head/sys/amd64/amd64/machdep.c	Tue Mar 20 17:43:50 2018	(r331252)
@@ -2597,6 +2597,31 @@ clear_pcb_flags(struct pcb *pcb, const u_int flags)
 	    : "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
 
 /*

Modified: head/sys/amd64/include/md_var.h
==============================================================================
--- head/sys/amd64/include/md_var.h	Tue Mar 20 17:41:54 2018	(r331251)
+++ head/sys/amd64/include/md_var.h	Tue Mar 20 17:43:50 2018	(r331252)
@@ -53,6 +53,8 @@ void	amd64_conf_fast_syscall(void);
 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));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803201743.w2KHhoF9055658>