From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v2 1/3] console: allow log level threshold adjustments Date: Fri, 04 Mar 2016 09:46:32 -0700 Message-ID: <56D9C9F802000078000D992D@prv-mh.provo.novell.com> References: <56D9C80702000078000D9910@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartA49326F8.1__=" Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.84) (envelope-from ) id 1abss8-0002rM-KV for xen-devel@lists.xenproject.org; Fri, 04 Mar 2016 16:46:36 +0000 In-Reply-To: <56D9C80702000078000D9910@prv-mh.provo.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Keir Fraser , Ian Jackson , Tim Deegan List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartA49326F8.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline ... from serial console and via sysctl so that one doesn't always need to reboot to see more / less messages. Note that upper thresholds driven from the serial console are sticky, i.e. while they get adjusted upwards when the lower threshold would otherwise end up above the upper one, they don't get adjusted when reducing the lower one. Full flexibility is available only via the sysctl interface. Signed-off-by: Jan Beulich --- v2: Add sysctl. --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -460,6 +460,10 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xe ret =3D tmem_control(&op->u.tmem_op); break; =20 + case XEN_SYSCTL_loglvl_op: + ret =3D console_loglvl_op(&op->u.loglvl); + break; + default: ret =3D arch_do_sysctl(op, u_sysctl); copyback =3D 0; --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -168,7 +168,7 @@ static void __init parse_guest_loglvl(ch _parse_loglvl(s, &xenlog_guest_lower_thresh, &xenlog_guest_upper_thres= h); } =20 -static char * __init loglvl_str(int lvl) +static char *loglvl_str(int lvl) { switch ( lvl ) { @@ -181,6 +181,119 @@ static char * __init loglvl_str(int lvl) return "???"; } =20 +static int *__read_mostly upper_thresh_adj =3D &xenlog_upper_thresh; +static int *__read_mostly lower_thresh_adj =3D &xenlog_lower_thresh; +static const char *__read_mostly thresh_adj =3D "standard"; + +static void do_toggle_guest(unsigned char key, struct cpu_user_regs = *regs) +{ + if ( upper_thresh_adj =3D=3D &xenlog_upper_thresh ) + { + upper_thresh_adj =3D &xenlog_guest_upper_thresh; + lower_thresh_adj =3D &xenlog_guest_lower_thresh; + thresh_adj =3D "guest"; + } + else + { + upper_thresh_adj =3D &xenlog_upper_thresh; + lower_thresh_adj =3D &xenlog_lower_thresh; + thresh_adj =3D "standard"; + } + printk("'%c' pressed -> %s log level adjustments enabled\n", + key, thresh_adj); +} + +static void do_adj_thresh(unsigned char key) +{ + if ( *upper_thresh_adj < *lower_thresh_adj ) + *upper_thresh_adj =3D *lower_thresh_adj; + printk("'%c' pressed -> %s log level: %s (rate limited %s)\n", + key, thresh_adj, loglvl_str(*lower_thresh_adj), + loglvl_str(*upper_thresh_adj)); +} + +static void do_inc_thresh(unsigned char key, struct cpu_user_regs *regs) +{ + ++*lower_thresh_adj; + do_adj_thresh(key); +} + +static void do_dec_thresh(unsigned char key, struct cpu_user_regs *regs) +{ + if ( *lower_thresh_adj ) + --*lower_thresh_adj; + do_adj_thresh(key); +} + +static void __putstr(const char *); +static void printk_start_of_line(const char *); + +static void do_loglvl_op(const struct xen_sysctl_loglvl_thresh *op, + int *lower, int *upper, const char *which) +{ + if ( op->lower_thresh < 0 && op->upper_thresh < 0 ) + return; + + if ( op->lower_thresh >=3D 0 ) + *lower =3D op->lower_thresh; + + if ( op->upper_thresh >=3D 0 ) + *upper =3D op->upper_thresh; + + if ( *upper < *lower ) + { + if ( op->upper_thresh < 0 ) + *upper =3D *lower; + else + *lower =3D *upper; + } + + if ( printk_ratelimit() ) + { + spin_lock_irq(&console_lock); + printk_start_of_line("(XEN) "); + __putstr(which); + __putstr(" log level: "); + __putstr(loglvl_str(*lower)); + __putstr(" (rate limited "); + __putstr(loglvl_str(*upper)); + __putstr(")\n"); + spin_unlock_irq(&console_lock); + } +} + +int console_loglvl_op(struct xen_sysctl_loglvl_op *op) +{ + switch ( op->cmd ) + { + default: + return -EOPNOTSUPP; + + case XEN_SYSCTL_LOGLVL_set: + if ( (op->host.lower_thresh >=3D 0 && op->host.upper_thresh >=3D = 0 && + op->host.lower_thresh > op->host.upper_thresh) || + (op->guest.lower_thresh >=3D 0 && op->guest.upper_thresh = >=3D 0 && + op->guest.lower_thresh > op->guest.upper_thresh) ) + return -EINVAL; + + do_loglvl_op(&op->host, &xenlog_lower_thresh, + &xenlog_upper_thresh, "standard"); + do_loglvl_op(&op->guest, &xenlog_guest_lower_thresh, + &xenlog_guest_upper_thresh, "guest"); + + /* fall through */ + case XEN_SYSCTL_LOGLVL_get: + op->host.lower_thresh =3D xenlog_lower_thresh; + op->host.upper_thresh =3D xenlog_upper_thresh; + + op->guest.lower_thresh =3D xenlog_guest_lower_thresh; + op->guest.upper_thresh =3D xenlog_guest_upper_thresh; + + break; + } + + return 0; +} /* * ******************************************************** * *************** ACCESS TO CONSOLE RING ***************** @@ -833,6 +946,12 @@ void __init console_endboot(void) =20 register_keyhandler('w', dump_console_ring_key, "synchronously dump console ring buffer (dmesg)", = 0); + register_irq_keyhandler('+', &do_inc_thresh, + "increase log level threshold", 0); + register_irq_keyhandler('-', &do_dec_thresh, + "decrease log level threshold", 0); + register_irq_keyhandler('G', &do_toggle_guest, + "toggle host/guest log level adjustment", 0); =20 /* Serial input is directed to DOM0 by default. */ switch_serial_input(); --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -766,6 +766,17 @@ struct xen_sysctl_tmem_op { typedef struct xen_sysctl_tmem_op xen_sysctl_tmem_op_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tmem_op_t); =20 +/* XEN_SYSCTL_loglvl_op */ +#define XEN_SYSCTL_LOGLVL_get 0 +#define XEN_SYSCTL_LOGLVL_set 1 +struct xen_sysctl_loglvl_op { + uint32_t cmd; /* XEN_SYSCTL_LOGLVL_* */ + struct xen_sysctl_loglvl_thresh { + /* Negative values mean "no adjustment". */ + int32_t lower_thresh, upper_thresh; + } host, guest; +}; + struct xen_sysctl { uint32_t cmd; #define XEN_SYSCTL_readconsole 1 @@ -791,6 +802,7 @@ struct xen_sysctl { #define XEN_SYSCTL_pcitopoinfo 22 #define XEN_SYSCTL_psr_cat_op 23 #define XEN_SYSCTL_tmem_op 24 +#define XEN_SYSCTL_loglvl_op 25 uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { struct xen_sysctl_readconsole readconsole; @@ -816,6 +828,7 @@ struct xen_sysctl { struct xen_sysctl_psr_cmt_op psr_cmt_op; struct xen_sysctl_psr_cat_op psr_cat_op; struct xen_sysctl_tmem_op tmem_op; + struct xen_sysctl_loglvl_op loglvl; uint8_t pad[128]; } u; }; --- a/xen/include/xen/console.h +++ b/xen/include/xen/console.h @@ -12,6 +12,8 @@ =20 struct xen_sysctl_readconsole; long read_console_ring(struct xen_sysctl_readconsole *op); +struct xen_sysctl_loglvl_op; +int console_loglvl_op(struct xen_sysctl_loglvl_op *); =20 void console_init_preirq(void); void console_init_ring(void); --=__PartA49326F8.1__= Content-Type: text/plain; name="loglvl-adjust.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="loglvl-adjust.patch" console: allow log level threshold adjustments=0A=0A... from serial = console and via sysctl so that one doesn't always need=0Ato reboot to see = more / less messages.=0A=0ANote that upper thresholds driven from the = serial console are sticky,=0Ai.e. while they get adjusted upwards when the = lower threshold would=0Aotherwise end up above the upper one, they don't = get adjusted when=0Areducing the lower one. Full flexibility is available = only via the=0Asysctl interface.=0A=0ASigned-off-by: Jan Beulich =0A---=0Av2: Add sysctl.=0A=0A--- a/xen/common/sysctl.c=0A+++ = b/xen/common/sysctl.c=0A@@ -460,6 +460,10 @@ long do_sysctl(XEN_GUEST_HANDL= E_PARAM(xe=0A ret =3D tmem_control(&op->u.tmem_op);=0A = break;=0A =0A+ case XEN_SYSCTL_loglvl_op:=0A+ ret =3D console_log= lvl_op(&op->u.loglvl);=0A+ break;=0A+=0A default:=0A = ret =3D arch_do_sysctl(op, u_sysctl);=0A copyback =3D 0;=0A--- = a/xen/drivers/char/console.c=0A+++ b/xen/drivers/char/console.c=0A@@ = -168,7 +168,7 @@ static void __init parse_guest_loglvl(ch=0A _parse_log= lvl(s, &xenlog_guest_lower_thresh, &xenlog_guest_upper_thresh);=0A }=0A = =0A-static char * __init loglvl_str(int lvl)=0A+static char *loglvl_str(int= lvl)=0A {=0A switch ( lvl )=0A {=0A@@ -181,6 +181,119 @@ static = char * __init loglvl_str(int lvl)=0A return "???";=0A }=0A =0A+static = int *__read_mostly upper_thresh_adj =3D &xenlog_upper_thresh;=0A+static = int *__read_mostly lower_thresh_adj =3D &xenlog_lower_thresh;=0A+static = const char *__read_mostly thresh_adj =3D "standard";=0A+=0A+static void = do_toggle_guest(unsigned char key, struct cpu_user_regs *regs)=0A+{=0A+ = if ( upper_thresh_adj =3D=3D &xenlog_upper_thresh )=0A+ {=0A+ = upper_thresh_adj =3D &xenlog_guest_upper_thresh;=0A+ lower_thresh_ad= j =3D &xenlog_guest_lower_thresh;=0A+ thresh_adj =3D "guest";=0A+ = }=0A+ else=0A+ {=0A+ upper_thresh_adj =3D &xenlog_upper_thres= h;=0A+ lower_thresh_adj =3D &xenlog_lower_thresh;=0A+ = thresh_adj =3D "standard";=0A+ }=0A+ printk("'%c' pressed -> %s log = level adjustments enabled\n",=0A+ key, thresh_adj);=0A+}=0A+=0A+s= tatic void do_adj_thresh(unsigned char key)=0A+{=0A+ if ( *upper_thresh_= adj < *lower_thresh_adj )=0A+ *upper_thresh_adj =3D *lower_thresh_ad= j;=0A+ printk("'%c' pressed -> %s log level: %s (rate limited %s)\n",=0A= + key, thresh_adj, loglvl_str(*lower_thresh_adj),=0A+ = loglvl_str(*upper_thresh_adj));=0A+}=0A+=0A+static void do_inc_thresh(unsig= ned char key, struct cpu_user_regs *regs)=0A+{=0A+ ++*lower_thresh_adj;= =0A+ do_adj_thresh(key);=0A+}=0A+=0A+static void do_dec_thresh(unsigned = char key, struct cpu_user_regs *regs)=0A+{=0A+ if ( *lower_thresh_adj = )=0A+ --*lower_thresh_adj;=0A+ do_adj_thresh(key);=0A+}=0A+=0A+st= atic void __putstr(const char *);=0A+static void printk_start_of_line(const= char *);=0A+=0A+static void do_loglvl_op(const struct xen_sysctl_loglvl_th= resh *op,=0A+ int *lower, int *upper, const char = *which)=0A+{=0A+ if ( op->lower_thresh < 0 && op->upper_thresh < 0 = )=0A+ return;=0A+=0A+ if ( op->lower_thresh >=3D 0 )=0A+ = *lower =3D op->lower_thresh;=0A+=0A+ if ( op->upper_thresh >=3D 0 )=0A+ = *upper =3D op->upper_thresh;=0A+=0A+ if ( *upper < *lower )=0A+ = {=0A+ if ( op->upper_thresh < 0 )=0A+ *upper =3D = *lower;=0A+ else=0A+ *lower =3D *upper;=0A+ }=0A+=0A+ = if ( printk_ratelimit() )=0A+ {=0A+ spin_lock_irq(&console_loc= k);=0A+ printk_start_of_line("(XEN) ");=0A+ __putstr(which);= =0A+ __putstr(" log level: ");=0A+ __putstr(loglvl_str(*lower= ));=0A+ __putstr(" (rate limited ");=0A+ __putstr(loglvl_str(= *upper));=0A+ __putstr(")\n");=0A+ spin_unlock_irq(&console_l= ock);=0A+ }=0A+}=0A+=0A+int console_loglvl_op(struct xen_sysctl_loglvl_o= p *op)=0A+{=0A+ switch ( op->cmd )=0A+ {=0A+ default:=0A+ = return -EOPNOTSUPP;=0A+=0A+ case XEN_SYSCTL_LOGLVL_set:=0A+ if ( = (op->host.lower_thresh >=3D 0 && op->host.upper_thresh >=3D 0 &&=0A+ = op->host.lower_thresh > op->host.upper_thresh) ||=0A+ = (op->guest.lower_thresh >=3D 0 && op->guest.upper_thresh >=3D 0 &&=0A+ = op->guest.lower_thresh > op->guest.upper_thresh) )=0A+ = return -EINVAL;=0A+=0A+ do_loglvl_op(&op->host, &xenlog_lower_thresh= ,=0A+ &xenlog_upper_thresh, "standard");=0A+ = do_loglvl_op(&op->guest, &xenlog_guest_lower_thresh,=0A+ = &xenlog_guest_upper_thresh, "guest");=0A+=0A+ /* fall through = */=0A+ case XEN_SYSCTL_LOGLVL_get:=0A+ op->host.lower_thresh =3D = xenlog_lower_thresh;=0A+ op->host.upper_thresh =3D xenlog_upper_thre= sh;=0A+=0A+ op->guest.lower_thresh =3D xenlog_guest_lower_thresh;=0A= + op->guest.upper_thresh =3D xenlog_guest_upper_thresh;=0A+=0A+ = break;=0A+ }=0A+=0A+ return 0;=0A+}=0A /*=0A * ******************= **************************************=0A * *************** ACCESS TO = CONSOLE RING *****************=0A@@ -833,6 +946,12 @@ void __init = console_endboot(void)=0A =0A register_keyhandler('w', dump_console_ring= _key,=0A "synchronously dump console ring buffer = (dmesg)", 0);=0A+ register_irq_keyhandler('+', &do_inc_thresh,=0A+ = "increase log level threshold", 0);=0A+ register_i= rq_keyhandler('-', &do_dec_thresh,=0A+ = "decrease log level threshold", 0);=0A+ register_irq_keyhandler('G', = &do_toggle_guest,=0A+ "toggle host/guest log = level adjustment", 0);=0A =0A /* Serial input is directed to DOM0 by = default. */=0A switch_serial_input();=0A--- a/xen/include/public/sysctl= .h=0A+++ b/xen/include/public/sysctl.h=0A@@ -766,6 +766,17 @@ struct = xen_sysctl_tmem_op {=0A typedef struct xen_sysctl_tmem_op xen_sysctl_tmem_o= p_t;=0A DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tmem_op_t);=0A =0A+/* XEN_SYSCTL= _loglvl_op */=0A+#define XEN_SYSCTL_LOGLVL_get 0=0A+#define XEN_SYSCTL_LOGL= VL_set 1=0A+struct xen_sysctl_loglvl_op {=0A+ uint32_t cmd; /* = XEN_SYSCTL_LOGLVL_* */=0A+ struct xen_sysctl_loglvl_thresh {=0A+ = /* Negative values mean "no adjustment". */=0A+ int32_t lower_thresh= , upper_thresh;=0A+ } host, guest;=0A+};=0A+=0A struct xen_sysctl {=0A = uint32_t cmd;=0A #define XEN_SYSCTL_readconsole = 1=0A@@ -791,6 +802,7 @@ struct xen_sysctl {=0A #define XEN_SYSCTL_pcitopoin= fo 22=0A #define XEN_SYSCTL_psr_cat_op = 23=0A #define XEN_SYSCTL_tmem_op 24=0A+#define = XEN_SYSCTL_loglvl_op 25=0A uint32_t interface_versi= on; /* XEN_SYSCTL_INTERFACE_VERSION */=0A union {=0A struct = xen_sysctl_readconsole readconsole;=0A@@ -816,6 +828,7 @@ struct = xen_sysctl {=0A struct xen_sysctl_psr_cmt_op psr_cmt_op;=0A = struct xen_sysctl_psr_cat_op psr_cat_op;=0A struct = xen_sysctl_tmem_op tmem_op;=0A+ struct xen_sysctl_loglvl_o= p loglvl;=0A uint8_t = pad[128];=0A } u;=0A };=0A--- a/xen/include/xen/console.h=0A+++ = b/xen/include/xen/console.h=0A@@ -12,6 +12,8 @@=0A =0A struct xen_sysctl_re= adconsole;=0A long read_console_ring(struct xen_sysctl_readconsole = *op);=0A+struct xen_sysctl_loglvl_op;=0A+int console_loglvl_op(struct = xen_sysctl_loglvl_op *);=0A =0A void console_init_preirq(void);=0A void = console_init_ring(void);=0A --=__PartA49326F8.1__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwOi8vbGlzdHMueGVuLm9y Zy94ZW4tZGV2ZWwK --=__PartA49326F8.1__=--