From 33f8cfdfe4e624b6c07a51f42bee618a7b6b9d19 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Thu, 13 Feb 2020 13:58:34 +0000 Subject: [PATCH 01/39] Whitespace cleanup. No functional change. Sponsored by: Netflix, Inc. --- sys/netinet/tcp_log_buf.h | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/sys/netinet/tcp_log_buf.h b/sys/netinet/tcp_log_buf.h index 5b470a541504..545a7462f593 100644 --- a/sys/netinet/tcp_log_buf.h +++ b/sys/netinet/tcp_log_buf.h @@ -130,7 +130,7 @@ struct tcp_log_buffer int tlb_state; /* TCPCB t_state */ uint32_t tlb_starttime; /* TCPCB t_starttime */ - uint32_t tlb_iss; /* TCPCB iss */ + uint32_t tlb_iss; /* TCPCB iss */ uint32_t tlb_flags; /* TCPCB flags */ uint32_t tlb_snd_una; /* TCPCB snd_una */ uint32_t tlb_snd_max; /* TCPCB snd_max */ @@ -145,12 +145,12 @@ struct tcp_log_buffer uint32_t tlb_rcv_adv; /* TCPCB rcv_adv */ uint32_t tlb_rcv_nxt; /* TCPCB rcv_nxt */ tcp_seq tlb_sack_newdata; /* TCPCB sack_newdata */ - uint32_t tlb_rcv_wnd; /* TCPCB rcv_wnd */ + uint32_t tlb_rcv_wnd; /* TCPCB rcv_wnd */ uint32_t tlb_dupacks; /* TCPCB t_dupacks */ int tlb_segqlen; /* TCPCB segqlen */ int tlb_snd_numholes; /* TCPCB snd_numholes */ - uint32_t tlb_flex1; /* Event specific information */ - uint32_t tlb_flex2; /* Event specific information */ + uint32_t tlb_flex1; /* Event specific information */ + uint32_t tlb_flex2; /* Event specific information */ uint8_t tlb_snd_scale:4, /* TCPCB snd_scale */ tlb_rcv_scale:4; /* TCPCB rcv_scale */ uint8_t _pad[3]; /* Padding */ @@ -169,15 +169,15 @@ struct tcp_log_buffer } ALIGN_TCP_LOG; enum tcp_log_events { - TCP_LOG_IN = 1, /* Incoming packet 1 */ - TCP_LOG_OUT, /* Transmit (without other event) 2 */ - TCP_LOG_RTO, /* Retransmit timeout 3 */ - TCP_LOG_TF_ACK, /* Transmit due to TF_ACK 4 */ - TCP_LOG_BAD_RETRAN, /* Detected bad retransmission 5 */ - TCP_LOG_PRR, /* Doing PRR 6 */ - TCP_LOG_REORDER,/* Detected reorder 7 */ - TCP_LOG_HPTS, /* Hpts sending a packet 8 */ - BBR_LOG_BBRUPD, /* We updated BBR info 9 */ + TCP_LOG_IN = 1, /* Incoming packet 1 */ + TCP_LOG_OUT, /* Transmit (without other event) 2 */ + TCP_LOG_RTO, /* Retransmit timeout 3 */ + TCP_LOG_TF_ACK, /* Transmit due to TF_ACK 4 */ + TCP_LOG_BAD_RETRAN, /* Detected bad retransmission 5 */ + TCP_LOG_PRR, /* Doing PRR 6 */ + TCP_LOG_REORDER, /* Detected reorder 7 */ + TCP_LOG_HPTS, /* Hpts sending a packet 8 */ + BBR_LOG_BBRUPD, /* We updated BBR info 9 */ BBR_LOG_BBRSND, /* We did a slot calculation and sending is done 10 */ BBR_LOG_ACKCLEAR, /* A ack clears all outstanding 11 */ BBR_LOG_INQUEUE, /* The tcb had a packet input to it 12 */ @@ -195,8 +195,8 @@ enum tcp_log_events { BBR_LOG_PERSIST, /* BBR changed to/from a persists 24 */ TCP_LOG_FLOWEND, /* End of a flow 25 */ BBR_LOG_RTO, /* BBR's timeout includes BBR info 26 */ - BBR_LOG_DOSEG_DONE, /* hpts do_segment completes 27 */ - BBR_LOG_EXIT_GAIN, /* hpts do_segment completes 28 */ + BBR_LOG_DOSEG_DONE, /* hpts do_segment completes 27 */ + BBR_LOG_EXIT_GAIN, /* hpts do_segment completes 28 */ BBR_LOG_THRESH_CALC, /* Doing threshold calculation 29 */ BBR_LOG_EXTRACWNDGAIN, /* Removed 30 */ TCP_LOG_USERSEND, /* User level sends data 31 */ @@ -204,29 +204,29 @@ enum tcp_log_events { BBR_LOG_STATE_TARGET, /* Log of target at state 33 */ BBR_LOG_TIME_EPOCH, /* A timed based Epoch occured 34 */ BBR_LOG_TO_PROCESS, /* A to was processed 35 */ - BBR_LOG_BBRTSO, /* TSO update 36 */ - BBR_LOG_HPTSDIAG, /* Hpts diag insert 37 */ + BBR_LOG_BBRTSO, /* TSO update 36 */ + BBR_LOG_HPTSDIAG, /* Hpts diag insert 37 */ BBR_LOG_LOWGAIN, /* Low gain accounting 38 */ BBR_LOG_PROGRESS, /* Progress timer event 39 */ - TCP_LOG_SOCKET_OPT, /* A socket option is set 40 */ + TCP_LOG_SOCKET_OPT, /* A socket option is set 40 */ BBR_LOG_TIMERPREP, /* A BBR var to debug out TLP issues 41 */ - BBR_LOG_ENOBUF_JMP, /* We had a enobuf jump 42 */ - BBR_LOG_HPTSI_CALC, /* calc the hptsi time 43 */ + BBR_LOG_ENOBUF_JMP, /* We had a enobuf jump 42 */ + BBR_LOG_HPTSI_CALC, /* calc the hptsi time 43 */ BBR_LOG_RTT_SHRINKS, /* We had a log reduction of rttProp 44 */ - BBR_LOG_BW_RED_EV, /* B/W reduction events 45 */ + BBR_LOG_BW_RED_EV, /* B/W reduction events 45 */ BBR_LOG_REDUCE, /* old bbr log reduce for 4.1 and earlier 46*/ TCP_LOG_RTT, /* A rtt (in useconds) is being sampled and applied to the srtt algo 47 */ - BBR_LOG_SETTINGS_CHG, /* Settings changed for loss response 48 */ - BBR_LOG_SRTT_GAIN_EVENT, /* SRTT gaining -- now not used 49 */ - TCP_LOG_REASS, /* Reassembly buffer logging 50 */ - TCP_HDWR_TLS, /* TCP Hardware TLS logs 51 */ - BBR_LOG_HDWR_PACE, /* TCP Hardware pacing log 52 */ - BBR_LOG_TSTMP_VAL, /* Temp debug timestamp validation 53 */ - TCP_LOG_CONNEND, /* End of connection 54 */ - TCP_LOG_LRO, /* LRO entry 55 */ - TCP_SACK_FILTER_RES, /* Results of SACK Filter 56 */ - TCP_SAD_DETECTION, /* Sack Attack Detection 57 */ - TCP_LOG_END /* End (keep at end) 58 */ + BBR_LOG_SETTINGS_CHG, /* Settings changed for loss response 48 */ + BBR_LOG_SRTT_GAIN_EVENT, /* SRTT gaining -- now not used 49 */ + TCP_LOG_REASS, /* Reassembly buffer logging 50 */ + TCP_HDWR_TLS, /* TCP Hardware TLS logs 51 */ + BBR_LOG_HDWR_PACE, /* TCP Hardware pacing log 52 */ + BBR_LOG_TSTMP_VAL, /* Temp debug timestamp validation 53 */ + TCP_LOG_CONNEND, /* End of connection 54 */ + TCP_LOG_LRO, /* LRO entry 55 */ + TCP_SACK_FILTER_RES, /* Results of SACK Filter 56 */ + TCP_SAD_DETECTION, /* Sack Attack Detection 57 */ + TCP_LOG_END /* End (keep at end) 58 */ }; enum tcp_log_states { @@ -296,8 +296,8 @@ struct tcp_log_dev_log_queue { do { \ if (tp->t_logstate != TCP_LOG_STATE_OFF) \ tcp_log_event_(tp, th, rxbuf, txbuf, eventid, \ - errornum, len, stackinfo, th_hostorder, \ - tp->t_output_caller, __func__, __LINE__, tv); \ + errornum, len, stackinfo, th_hostorder, \ + tp->t_output_caller, __func__, __LINE__, tv);\ } while (0) /* @@ -326,11 +326,11 @@ struct tcp_log_dev_log_queue { if (tcp_log_verbose) \ TCP_LOG_EVENT_VERBOSE(tp, th, rxbuf, txbuf, \ eventid, errornum, len, stackinfo, \ - th_hostorder, NULL); \ + th_hostorder, NULL); \ else if (tp->t_logstate != TCP_LOG_STATE_OFF) \ tcp_log_event_(tp, th, rxbuf, txbuf, eventid, \ errornum, len, stackinfo, th_hostorder, \ - NULL, NULL, 0, NULL); \ + NULL, NULL, 0, NULL); \ } while (0) #endif /* TCP_LOG_FORCEVERBOSE */ #define TCP_LOG_EVENTP(tp, th, rxbuf, txbuf, eventid, errornum, len, stackinfo, th_hostorder, tv) \ From 475b483aeef96d8bf47159f06761104d92c58c8c Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Thu, 13 Feb 2020 14:09:09 +0000 Subject: [PATCH 02/39] tests: Enable net tests We have a number of tests in the net subdirectory that were not executed. List the net directory so we run those tests. --- tests/sys/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/sys/Makefile b/tests/sys/Makefile index fa3f2f949626..cec72d922e53 100644 --- a/tests/sys/Makefile +++ b/tests/sys/Makefile @@ -19,6 +19,7 @@ TESTS_SUBDIRS+= kern TESTS_SUBDIRS+= kqueue TESTS_SUBDIRS+= mac TESTS_SUBDIRS+= mqueue +TESTS_SUBDIRS+= net TESTS_SUBDIRS+= netinet TESTS_SUBDIRS+= netinet6 TESTS_SUBDIRS+= netipsec From a3574665924113b9ac707dabed2013c722e602c7 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Thu, 13 Feb 2020 15:14:46 +0000 Subject: [PATCH 03/39] sack_newdata and snd_recover hold the same value. Therefore, use only a single instance: use snd_recover also where sack_newdata was used. Submitted by: Richard Scheffenegger Differential Revision: https://reviews.freebsd.org/D18811 --- cddl/lib/libdtrace/tcp.d | 2 +- sys/netinet/tcp_input.c | 2 +- sys/netinet/tcp_log_buf.c | 1 - sys/netinet/tcp_log_buf.h | 3 +-- sys/netinet/tcp_output.c | 2 +- sys/netinet/tcp_sack.c | 2 +- sys/netinet/tcp_usrreq.c | 4 ++-- sys/netinet/tcp_var.h | 2 -- 8 files changed, 7 insertions(+), 11 deletions(-) diff --git a/cddl/lib/libdtrace/tcp.d b/cddl/lib/libdtrace/tcp.d index 7e3f67a9aa87..afcfdfadaf1e 100644 --- a/cddl/lib/libdtrace/tcp.d +++ b/cddl/lib/libdtrace/tcp.d @@ -244,7 +244,7 @@ translator tcpsinfo_t < struct tcpcb *p > { tcps_cwnd_ssthresh = p == NULL ? -1 : p->snd_ssthresh; tcps_srecover = p == NULL ? -1 : p->snd_recover; tcps_sack_fack = p == NULL ? 0 : p->snd_fack; - tcps_sack_snxt = p == NULL ? 0 : p->sack_newdata; + tcps_sack_snxt = p == NULL ? 0 : p->snd_recover; tcps_rto = p == NULL ? -1 : (p->t_rxtcur * 1000) / `hz; tcps_mss = p == NULL ? -1 : p->t_maxseg; tcps_retransmit = p == NULL ? -1 : p->t_rxtshift > 0 ? 1 : 0; diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index d23a364e2fc2..4bc42aea040f 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -2564,7 +2564,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, if (tp->t_flags & TF_SACK_PERMIT) { TCPSTAT_INC( tcps_sack_recovery_episode); - tp->sack_newdata = tp->snd_nxt; + tp->snd_recover = tp->snd_nxt; tp->snd_cwnd = maxseg; (void) tp->t_fb->tfb_tcp_output(tp); goto drop; diff --git a/sys/netinet/tcp_log_buf.c b/sys/netinet/tcp_log_buf.c index 1e2603680a46..d5cdcb404a21 100644 --- a/sys/netinet/tcp_log_buf.c +++ b/sys/netinet/tcp_log_buf.c @@ -1686,7 +1686,6 @@ tcp_log_event_(struct tcpcb *tp, struct tcphdr *th, struct sockbuf *rxbuf, COPY_STAT(rcv_up); COPY_STAT(rcv_adv); COPY_STAT(rcv_nxt); - COPY_STAT(sack_newdata); COPY_STAT(rcv_wnd); COPY_STAT_T(dupacks); COPY_STAT_T(segqlen); diff --git a/sys/netinet/tcp_log_buf.h b/sys/netinet/tcp_log_buf.h index 545a7462f593..1f7cf3605116 100644 --- a/sys/netinet/tcp_log_buf.h +++ b/sys/netinet/tcp_log_buf.h @@ -32,7 +32,7 @@ #define TCP_LOG_REASON_LEN 32 #define TCP_LOG_TAG_LEN 32 -#define TCP_LOG_BUF_VER (7) +#define TCP_LOG_BUF_VER (8) /* * Because the (struct tcp_log_buffer) includes 8-byte uint64_t's, it requires @@ -144,7 +144,6 @@ struct tcp_log_buffer uint32_t tlb_rcv_up; /* TCPCB rcv_up */ uint32_t tlb_rcv_adv; /* TCPCB rcv_adv */ uint32_t tlb_rcv_nxt; /* TCPCB rcv_nxt */ - tcp_seq tlb_sack_newdata; /* TCPCB sack_newdata */ uint32_t tlb_rcv_wnd; /* TCPCB rcv_wnd */ uint32_t tlb_dupacks; /* TCPCB t_dupacks */ int tlb_segqlen; /* TCPCB segqlen */ diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index e563dd9bda03..11386c4d1706 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -420,7 +420,7 @@ tcp_output(struct tcpcb *tp) */ if (len > 0) { cwin = tp->snd_cwnd - - (tp->snd_nxt - tp->sack_newdata) - + (tp->snd_nxt - tp->snd_recover) - sack_bytes_rxmt; if (cwin < 0) cwin = 0; diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index c9874a37a1d8..90e25ea8a5e3 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -780,7 +780,7 @@ tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th) if ((BYTES_THIS_ACK(tp, th) / tp->t_maxseg) >= 2) num_segs = 2; tp->snd_cwnd = (tp->sackhint.sack_bytes_rexmit + - (tp->snd_nxt - tp->sack_newdata) + num_segs * tp->t_maxseg); + (tp->snd_nxt - tp->snd_recover) + num_segs * tp->t_maxseg); if (tp->snd_cwnd > tp->snd_ssthresh) tp->snd_cwnd = tp->snd_ssthresh; tp->t_flags |= TF_ACKNOW; diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 736dc4dab644..0113e431eb85 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -2806,8 +2806,8 @@ db_print_tcpcb(struct tcpcb *tp, const char *name, int indent) tp->snd_numholes, TAILQ_FIRST(&tp->snd_holes)); db_print_indent(indent); - db_printf("snd_fack: 0x%08x rcv_numsacks: %d sack_newdata: " - "0x%08x\n", tp->snd_fack, tp->rcv_numsacks, tp->sack_newdata); + db_printf("snd_fack: 0x%08x rcv_numsacks: %d\n", + tp->snd_fack, tp->rcv_numsacks); /* Skip sackblks, sackhint. */ diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index d8a71eb88542..3035d1518743 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -186,8 +186,6 @@ struct tcpcb { TAILQ_HEAD(sackhole_head, sackhole) snd_holes; /* SACK scoreboard (sorted) */ tcp_seq snd_fack; /* last seq number(+1) sack'd by rcv'r*/ - tcp_seq sack_newdata; /* New data xmitted in this recovery - episode starts at this seq number */ struct sackblk sackblks[MAX_SACK_BLKS]; /* seq nos. of sack blocks */ struct sackhint sackhint; /* SACK scoreboard hint */ int t_rttlow; /* smallest observerved RTT */ From f05cc0f136d2497436d01a0b0f4ca3f4e9ee6965 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 13 Feb 2020 15:28:56 +0000 Subject: [PATCH 04/39] sesutil: fix Coverity CIDs * 1411604: file descriptor leak * 1411586: memory leaks, null dereference on ENOMEM Reported by: Coverity Scan Coverity CIDs: 1411604, 1411586 Reviewed by: trasz MFC after: 2 weeks Sponsored by: Axcient Differential Revision: https://reviews.freebsd.org/D23651 --- usr.sbin/sesutil/sesutil.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/usr.sbin/sesutil/sesutil.c b/usr.sbin/sesutil/sesutil.c index f425c615b1c4..e3f76912da86 100644 --- a/usr.sbin/sesutil/sesutil.c +++ b/usr.sbin/sesutil/sesutil.c @@ -570,17 +570,17 @@ fetch_device_details(char *devnames, char **model, char **serial, off_t *size) { char ident[DISK_IDENT_SIZE]; struct diocgattr_arg arg; - char *device, *tmp; + char *tmp; off_t mediasize; + int comma; int fd; - tmp = strdup(devnames); + comma = (int)strcspn(devnames, ","); + asprintf(&tmp, "/dev/%.*s", comma, devnames); if (tmp == NULL) - err(1, "strdup"); - - device = strsep(&tmp, ","); - asprintf(&tmp, "/dev/%s", device); + err(1, "asprintf"); fd = open(tmp, O_RDONLY); + free(tmp); if (fd < 0) { /* * This can happen with a disk so broken it cannot @@ -589,6 +589,7 @@ fetch_device_details(char *devnames, char **model, char **serial, off_t *size) *model = strdup("?"); *serial = strdup("?"); *size = -1; + close(fd); return; } @@ -608,6 +609,7 @@ fetch_device_details(char *devnames, char **model, char **serial, off_t *size) *size = mediasize; else *size = -1; + close(fd); } static void From 66343a7bb25d038cba2e4e33ec997963d51f7d34 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Thu, 13 Feb 2020 15:42:14 +0000 Subject: [PATCH 05/39] Revert r357343: services: Add PROFInet and EtherCAT. Both are admitedly very niche features and no known users exist currently. I am doing a further review/update of the services file (see D23621) and both of these are not likely to be considered. --- usr.sbin/services_mkdb/services | 8 -------- 1 file changed, 8 deletions(-) diff --git a/usr.sbin/services_mkdb/services b/usr.sbin/services_mkdb/services index 77b552dad73f..4122cc0adaf7 100644 --- a/usr.sbin/services_mkdb/services +++ b/usr.sbin/services_mkdb/services @@ -2494,14 +2494,6 @@ wnn6_DS 26208/tcp #Wnn6 (Dserver) sgsap 29118/sctp #SGsAP in 3GPP sbcap 29168/sctp #SBcAP in 3GPP iuhsctpassoc 29169/sctp #HNBAP and RUA Common Association -profinet-rt 34962/tcp #PROFInet RT Unicast -profinet-rt 34962/udp #PROFInet RT Unicast -profinet-rtm 34963/tcp #PROFInet RT Multicast -profinet-rtm 34963/udp #PROFInet RT Multicast -profinet-cm 34964/tcp #PROFInet Context Manager -profinet-cm 34964/udp #PROFInet Context Manager -ethercat 34980/tcp #EtherCAT Port -ethercat 34980/udp #EhterCAT Port s1-control 36412/sctp #S1-Control Plane (3GPP) x2-control 36422/sctp #X2-Control Plane (3GPP) dbbrowse 47557/tcp #Databeam Corporation From d4028678f27c762603661745f86896cb2870109c Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Thu, 13 Feb 2020 16:03:12 +0000 Subject: [PATCH 06/39] Improve USB gaming keyboard support. Add support for decoding pressed keys as a bitmap. The keys in the bitmap are described in the interface specific HID descriptor. Some keyboards even have multiple input interfaces, only using the bitmap method when the event array is full. That typically means when more than seven keys are pressed simultaneously. The internals of the USB keyboard driver have been slightly reworked to keep track of all keys in a single bitmap having 256 bits. This bitmap is then divided into blocks of 64-bits as an optimisation. Simplify automatic key repeat logic, because only the last key pressed can be repeated. PR: 224592 PR: 233884 Tested by: Alex V. Petrov MFC after: 1 week Sponsored by: Mellanox Technologies --- sys/dev/usb/input/ukbd.c | 517 ++++++++++++++------------------------- 1 file changed, 182 insertions(+), 335 deletions(-) diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index 88f1035d70ef..c229a52d59d0 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -109,27 +109,21 @@ SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollrate, CTLFLAG_RWTUN, #define UKBD_EMULATE_ATSCANCODE 1 #define UKBD_DRIVER_NAME "ukbd" -#define UKBD_NMOD 8 /* units */ -#define UKBD_NKEYCODE 6 /* units */ -#define UKBD_IN_BUF_SIZE (2*(UKBD_NMOD + (2*UKBD_NKEYCODE))) /* bytes */ -#define UKBD_IN_BUF_FULL ((UKBD_IN_BUF_SIZE / 2) - 1) /* bytes */ +#define UKBD_NKEYCODE 256 /* units */ +#define UKBD_IN_BUF_SIZE (4 * UKBD_NKEYCODE) /* scancodes */ +#define UKBD_IN_BUF_FULL ((UKBD_IN_BUF_SIZE / 2) - 1) /* scancodes */ #define UKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */ #define UKBD_BUFFER_SIZE 64 /* bytes */ +#define UKBD_KEY_PRESSED(map, key) ({ \ + CTASSERT((key) >= 0 && (key) < UKBD_NKEYCODE); \ + ((map)[(key) / 64] & (1ULL << ((key) % 64))); \ +}) + +#define MOD_EJECT 0x01 +#define MOD_FN 0x02 struct ukbd_data { - uint16_t modifiers; -#define MOD_CONTROL_L 0x01 -#define MOD_CONTROL_R 0x10 -#define MOD_SHIFT_L 0x02 -#define MOD_SHIFT_R 0x20 -#define MOD_ALT_L 0x04 -#define MOD_ALT_R 0x40 -#define MOD_WIN_L 0x08 -#define MOD_WIN_R 0x80 -/* internal */ -#define MOD_EJECT 0x0100 -#define MOD_FN 0x0200 - uint8_t keycode[UKBD_NKEYCODE]; + uint64_t bitmap[howmany(UKBD_NKEYCODE, 64)]; }; enum { @@ -144,17 +138,10 @@ struct ukbd_softc { keymap_t sc_keymap; accentmap_t sc_accmap; fkeytab_t sc_fkeymap[UKBD_NFKEY]; + uint64_t sc_loc_key_valid[howmany(UKBD_NKEYCODE, 64)]; struct hid_location sc_loc_apple_eject; struct hid_location sc_loc_apple_fn; - struct hid_location sc_loc_ctrl_l; - struct hid_location sc_loc_ctrl_r; - struct hid_location sc_loc_shift_l; - struct hid_location sc_loc_shift_r; - struct hid_location sc_loc_alt_l; - struct hid_location sc_loc_alt_r; - struct hid_location sc_loc_win_l; - struct hid_location sc_loc_win_r; - struct hid_location sc_loc_events; + struct hid_location sc_loc_key[UKBD_NKEYCODE]; struct hid_location sc_loc_numlock; struct hid_location sc_loc_capslock; struct hid_location sc_loc_scrolllock; @@ -172,8 +159,7 @@ struct ukbd_softc { sbintime_t sc_co_basetime; int sc_delay; - uint32_t sc_ntime[UKBD_NKEYCODE]; - uint32_t sc_otime[UKBD_NKEYCODE]; + uint32_t sc_repeat_time; uint32_t sc_input[UKBD_IN_BUF_SIZE]; /* input buffer */ uint32_t sc_time_ms; uint32_t sc_composed_char; /* composed char code, if non-zero */ @@ -191,15 +177,6 @@ struct ukbd_softc { #define UKBD_FLAG_APPLE_EJECT 0x00000040 #define UKBD_FLAG_APPLE_FN 0x00000080 #define UKBD_FLAG_APPLE_SWAP 0x00000100 -#define UKBD_FLAG_CTRL_L 0x00000400 -#define UKBD_FLAG_CTRL_R 0x00000800 -#define UKBD_FLAG_SHIFT_L 0x00001000 -#define UKBD_FLAG_SHIFT_R 0x00002000 -#define UKBD_FLAG_ALT_L 0x00004000 -#define UKBD_FLAG_ALT_R 0x00008000 -#define UKBD_FLAG_WIN_L 0x00010000 -#define UKBD_FLAG_WIN_R 0x00020000 -#define UKBD_FLAG_EVENTS 0x00040000 #define UKBD_FLAG_NUMLOCK 0x00080000 #define UKBD_FLAG_CAPSLOCK 0x00100000 #define UKBD_FLAG_SCROLLLOCK 0x00200000 @@ -214,31 +191,23 @@ struct ukbd_softc { uint16_t sc_inputs; uint16_t sc_inputhead; uint16_t sc_inputtail; - uint16_t sc_modifiers; uint8_t sc_leds; /* store for async led requests */ uint8_t sc_iface_index; uint8_t sc_iface_no; uint8_t sc_id_apple_eject; uint8_t sc_id_apple_fn; - uint8_t sc_id_ctrl_l; - uint8_t sc_id_ctrl_r; - uint8_t sc_id_shift_l; - uint8_t sc_id_shift_r; - uint8_t sc_id_alt_l; - uint8_t sc_id_alt_r; - uint8_t sc_id_win_l; - uint8_t sc_id_win_r; - uint8_t sc_id_event; + uint8_t sc_id_loc_key[UKBD_NKEYCODE]; uint8_t sc_id_numlock; uint8_t sc_id_capslock; uint8_t sc_id_scrolllock; - uint8_t sc_id_events; uint8_t sc_kbd_id; + uint8_t sc_repeat_key; uint8_t sc_buffer[UKBD_BUFFER_SIZE]; }; +#define KEY_NONE 0x00 #define KEY_ERROR 0x01 #define KEY_PRESS 0 @@ -259,21 +228,6 @@ struct ukbd_softc { #define UKBD_UNLOCK() USB_MTX_UNLOCK(&Giant) #define UKBD_LOCK_ASSERT() USB_MTX_ASSERT(&Giant, MA_OWNED) -struct ukbd_mods { - uint32_t mask, key; -}; - -static const struct ukbd_mods ukbd_mods[UKBD_NMOD] = { - {MOD_CONTROL_L, 0xe0}, - {MOD_CONTROL_R, 0xe4}, - {MOD_SHIFT_L, 0xe1}, - {MOD_SHIFT_R, 0xe5}, - {MOD_ALT_L, 0xe2}, - {MOD_ALT_R, 0xe6}, - {MOD_WIN_L, 0xe3}, - {MOD_WIN_R, 0xe7}, -}; - #define NN 0 /* no translation */ /* * Translate USB keycodes to AT keyboard scancodes. @@ -347,8 +301,8 @@ static void ukbd_timeout(void *); static void ukbd_set_leds(struct ukbd_softc *, uint8_t); static int ukbd_set_typematic(keyboard_t *, int); #ifdef UKBD_EMULATE_ATSCANCODE -static uint32_t ukbd_atkeycode(int, int); -static int ukbd_key2scan(struct ukbd_softc *, int, int, int); +static uint32_t ukbd_atkeycode(int, const uint64_t *); +static int ukbd_key2scan(struct ukbd_softc *, int, const uint64_t *, int); #endif static uint32_t ukbd_read_char(keyboard_t *, int); static void ukbd_clear_state(keyboard_t *); @@ -371,16 +325,26 @@ static const struct evdev_methods ukbd_evdev_methods = { }; #endif -static uint8_t +static bool ukbd_any_key_pressed(struct ukbd_softc *sc) { - uint8_t i; - uint8_t j; + bool ret = false; + unsigned i; - for (j = i = 0; i < UKBD_NKEYCODE; i++) - j |= sc->sc_odata.keycode[i]; + for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++) + ret |= (sc->sc_odata.bitmap[i] != 0); + return (ret); +} - return (j ? 1 : 0); +static bool +ukbd_any_key_valid(struct ukbd_softc *sc) +{ + bool ret = false; + unsigned i; + + for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++) + ret |= (sc->sc_loc_key_valid[i] != 0); + return (ret); } static void @@ -522,99 +486,63 @@ ukbd_get_key(struct ukbd_softc *sc, uint8_t wait) static void ukbd_interrupt(struct ukbd_softc *sc) { - uint32_t n_mod; - uint32_t o_mod; - uint32_t now = sc->sc_time_ms; - int32_t dtime; - uint8_t key; - uint8_t i; - uint8_t j; + const uint32_t now = sc->sc_time_ms; + unsigned key; + bool old_keys; UKBD_LOCK_ASSERT(); - if (sc->sc_ndata.keycode[0] == KEY_ERROR) - return; + old_keys = ukbd_any_key_pressed(sc); - n_mod = sc->sc_ndata.modifiers; - o_mod = sc->sc_odata.modifiers; - if (n_mod != o_mod) { - for (i = 0; i < UKBD_NMOD; i++) { - if ((n_mod & ukbd_mods[i].mask) != - (o_mod & ukbd_mods[i].mask)) { - ukbd_put_key(sc, ukbd_mods[i].key | - ((n_mod & ukbd_mods[i].mask) ? - KEY_PRESS : KEY_RELEASE)); + /* Check for key changes */ + for (key = 0; key != UKBD_NKEYCODE; key++) { + const uint64_t mask = 1ULL << (key % 64); + const uint64_t delta = + sc->sc_odata.bitmap[key / 64] ^ + sc->sc_ndata.bitmap[key / 64]; + + if (mask == 1 && delta == 0) { + key += 63; + continue; /* skip empty areas */ + } else if (delta & mask) { + if (sc->sc_odata.bitmap[key / 64] & mask) { + ukbd_put_key(sc, key | KEY_RELEASE); + + /* clear repeating key, if any */ + if (sc->sc_repeat_key == key) + sc->sc_repeat_key = 0; + } else { + ukbd_put_key(sc, key | KEY_PRESS); + + /* set repeat time for last key */ + sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; + sc->sc_repeat_key = key; } } } - /* Check for released keys. */ - for (i = 0; i < UKBD_NKEYCODE; i++) { - key = sc->sc_odata.keycode[i]; - if (key == 0) { - continue; - } - for (j = 0; j < UKBD_NKEYCODE; j++) { - if (sc->sc_ndata.keycode[j] == 0) { - continue; - } - if (key == sc->sc_ndata.keycode[j]) { - goto rfound; - } - } - ukbd_put_key(sc, key | KEY_RELEASE); -rfound: ; - } - - /* Check for pressed keys. */ - for (i = 0; i < UKBD_NKEYCODE; i++) { - key = sc->sc_ndata.keycode[i]; - if (key == 0) { - continue; - } - sc->sc_ntime[i] = now + sc->sc_kbd.kb_delay1; - for (j = 0; j < UKBD_NKEYCODE; j++) { - if (sc->sc_odata.keycode[j] == 0) { - continue; - } - if (key == sc->sc_odata.keycode[j]) { - - /* key is still pressed */ - - sc->sc_ntime[i] = sc->sc_otime[j]; - dtime = (sc->sc_otime[j] - now); - - if (dtime > 0) { - /* time has not elapsed */ - goto pfound; - } - sc->sc_ntime[i] = now + sc->sc_kbd.kb_delay2; - break; - } - } - if (j == UKBD_NKEYCODE) { - /* New key - set initial delay and [re]start timer */ - sc->sc_co_basetime = sbinuptime(); - sc->sc_delay = sc->sc_kbd.kb_delay1; - ukbd_start_timer(sc); - } - ukbd_put_key(sc, key | KEY_PRESS); - - /* - * If any other key is presently down, force its repeat to be - * well in the future (100s). This makes the last key to be - * pressed do the autorepeat. - */ - for (j = 0; j != UKBD_NKEYCODE; j++) { - if (j != i) - sc->sc_ntime[j] = now + (100 * 1000); - } -pfound: ; - } + /* synchronize old data with new data */ sc->sc_odata = sc->sc_ndata; + + /* check if last key is still pressed */ + if (sc->sc_repeat_key != 0) { + const int32_t dtime = (sc->sc_repeat_time - now); - memcpy(sc->sc_otime, sc->sc_ntime, sizeof(sc->sc_otime)); + /* check if time has elapsed */ + if (dtime <= 0) { + ukbd_put_key(sc, sc->sc_repeat_key | KEY_PRESS); + sc->sc_repeat_time = now + sc->sc_kbd.kb_delay2; + } + } + /* check for first new key and set initial delay and [re]start timer */ + if (old_keys == false && ukbd_any_key_pressed(sc) == true) { + sc->sc_co_basetime = sbinuptime(); + sc->sc_delay = sc->sc_kbd.kb_delay1; + ukbd_start_timer(sc); + } + + /* wakeup keyboard system */ ukbd_event_keyinput(sc); } @@ -664,8 +592,9 @@ ukbd_timeout(void *arg) } } -static uint8_t -ukbd_apple_fn(uint8_t keycode) { +static uint32_t +ukbd_apple_fn(uint32_t keycode) +{ switch (keycode) { case 0x28: return 0x49; /* RETURN -> INSERT */ case 0x2a: return 0x4c; /* BACKSPACE -> DEL */ @@ -677,8 +606,9 @@ ukbd_apple_fn(uint8_t keycode) { } } -static uint8_t -ukbd_apple_swap(uint8_t keycode) { +static uint32_t +ukbd_apple_swap(uint32_t keycode) +{ switch (keycode) { case 0x35: return 0x64; case 0x64: return 0x35; @@ -691,9 +621,10 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) { struct ukbd_softc *sc = usbd_xfer_softc(xfer); struct usb_page_cache *pc; - uint8_t i; - uint8_t offset; + uint32_t i; uint8_t id; + uint8_t modifiers; + int offset; int len; UKBD_LOCK_ASSERT(); @@ -733,117 +664,72 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) /* clear temporary storage */ memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); + /* clear modifiers */ + modifiers = 0; + /* scan through HID data */ if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && (id == sc->sc_id_apple_eject)) { if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) - sc->sc_modifiers |= MOD_EJECT; - else - sc->sc_modifiers &= ~MOD_EJECT; + modifiers |= MOD_EJECT; } if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && (id == sc->sc_id_apple_fn)) { if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) - sc->sc_modifiers |= MOD_FN; - else - sc->sc_modifiers &= ~MOD_FN; - } - if ((sc->sc_flags & UKBD_FLAG_CTRL_L) && - (id == sc->sc_id_ctrl_l)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_ctrl_l)) - sc-> sc_modifiers |= MOD_CONTROL_L; - else - sc-> sc_modifiers &= ~MOD_CONTROL_L; - } - if ((sc->sc_flags & UKBD_FLAG_CTRL_R) && - (id == sc->sc_id_ctrl_r)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_ctrl_r)) - sc->sc_modifiers |= MOD_CONTROL_R; - else - sc->sc_modifiers &= ~MOD_CONTROL_R; - } - if ((sc->sc_flags & UKBD_FLAG_SHIFT_L) && - (id == sc->sc_id_shift_l)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_shift_l)) - sc->sc_modifiers |= MOD_SHIFT_L; - else - sc->sc_modifiers &= ~MOD_SHIFT_L; - } - if ((sc->sc_flags & UKBD_FLAG_SHIFT_R) && - (id == sc->sc_id_shift_r)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_shift_r)) - sc->sc_modifiers |= MOD_SHIFT_R; - else - sc->sc_modifiers &= ~MOD_SHIFT_R; - } - if ((sc->sc_flags & UKBD_FLAG_ALT_L) && - (id == sc->sc_id_alt_l)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_alt_l)) - sc->sc_modifiers |= MOD_ALT_L; - else - sc->sc_modifiers &= ~MOD_ALT_L; - } - if ((sc->sc_flags & UKBD_FLAG_ALT_R) && - (id == sc->sc_id_alt_r)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_alt_r)) - sc->sc_modifiers |= MOD_ALT_R; - else - sc->sc_modifiers &= ~MOD_ALT_R; - } - if ((sc->sc_flags & UKBD_FLAG_WIN_L) && - (id == sc->sc_id_win_l)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_win_l)) - sc->sc_modifiers |= MOD_WIN_L; - else - sc->sc_modifiers &= ~MOD_WIN_L; - } - if ((sc->sc_flags & UKBD_FLAG_WIN_R) && - (id == sc->sc_id_win_r)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_win_r)) - sc->sc_modifiers |= MOD_WIN_R; - else - sc->sc_modifiers &= ~MOD_WIN_R; + modifiers |= MOD_FN; } - sc->sc_ndata.modifiers = sc->sc_modifiers; + for (i = 0; i != UKBD_NKEYCODE; i++) { + const uint64_t valid = sc->sc_loc_key_valid[i / 64]; + const uint64_t mask = 1ULL << (i % 64); - if ((sc->sc_flags & UKBD_FLAG_EVENTS) && - (id == sc->sc_id_events)) { - i = sc->sc_loc_events.count; - if (i > UKBD_NKEYCODE) - i = UKBD_NKEYCODE; - if (i > len) - i = len; - while (i--) { - sc->sc_ndata.keycode[i] = - hid_get_data(sc->sc_buffer + i, len - i, - &sc->sc_loc_events); + if (mask == 1 && valid == 0) { + i += 63; + continue; /* skip empty areas */ + } else if (~valid & mask) { + continue; /* location is not valid */ + } else if (id != sc->sc_id_loc_key[i]) { + continue; /* invalid HID ID */ + } else if (i == 0) { + offset = sc->sc_loc_key[0].count; + if (offset < 0 || offset > len) + offset = len; + while (offset--) { + uint32_t key = + hid_get_data(sc->sc_buffer + offset, len - offset, + &sc->sc_loc_key[i]); + if (modifiers & MOD_FN) + key = ukbd_apple_fn(key); + if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) + key = ukbd_apple_swap(key); + if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE) + continue; + /* set key in bitmap */ + sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64); + } + } else if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_key[i])) { + uint32_t key = i; + + if (modifiers & MOD_FN) + key = ukbd_apple_fn(key); + if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) + key = ukbd_apple_swap(key); + if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE) + continue; + /* set key in bitmap */ + sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64); } } - #ifdef USB_DEBUG - DPRINTF("modifiers = 0x%04x\n", (int)sc->sc_modifiers); - for (i = 0; i < UKBD_NKEYCODE; i++) { - if (sc->sc_ndata.keycode[i]) { - DPRINTF("[%d] = 0x%02x\n", - (int)i, (int)sc->sc_ndata.keycode[i]); - } + DPRINTF("modifiers = 0x%04x\n", modifiers); + for (i = 0; i != UKBD_NKEYCODE; i++) { + const uint64_t valid = sc->sc_ndata.bitmap[i / 64]; + const uint64_t mask = 1ULL << (i % 64); + + if (valid & mask) + DPRINTF("Key 0x%02x pressed\n", i); } #endif - if (sc->sc_modifiers & MOD_FN) { - for (i = 0; i < UKBD_NKEYCODE; i++) { - sc->sc_ndata.keycode[i] = - ukbd_apple_fn(sc->sc_ndata.keycode[i]); - } - } - - if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) { - for (i = 0; i < UKBD_NKEYCODE; i++) { - sc->sc_ndata.keycode[i] = - ukbd_apple_swap(sc->sc_ndata.keycode[i]); - } - } - ukbd_interrupt(sc); case USB_ST_SETUP: @@ -1072,10 +958,14 @@ static void ukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len) { uint32_t flags; + uint32_t key; /* reset detected bits */ sc->sc_flags &= ~UKBD_FLAG_HID_MASK; + /* reset detected keys */ + memset(sc->sc_loc_key_valid, 0, sizeof(sc->sc_loc_key_valid)); + /* check if there is an ID byte */ sc->sc_kbd_size = hid_report_size(ptr, len, hid_input, &sc->sc_kbd_id); @@ -1098,84 +988,34 @@ ukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len) sc->sc_flags |= UKBD_FLAG_APPLE_FN; DPRINTFN(1, "Found Apple FN-key\n"); } - /* figure out some keys */ - if (hid_locate(ptr, len, - HID_USAGE2(HUP_KEYBOARD, 0xE0), - hid_input, 0, &sc->sc_loc_ctrl_l, &flags, - &sc->sc_id_ctrl_l)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_CTRL_L; - DPRINTFN(1, "Found left control\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(HUP_KEYBOARD, 0xE4), - hid_input, 0, &sc->sc_loc_ctrl_r, &flags, - &sc->sc_id_ctrl_r)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_CTRL_R; - DPRINTFN(1, "Found right control\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(HUP_KEYBOARD, 0xE1), - hid_input, 0, &sc->sc_loc_shift_l, &flags, - &sc->sc_id_shift_l)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_SHIFT_L; - DPRINTFN(1, "Found left shift\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(HUP_KEYBOARD, 0xE5), - hid_input, 0, &sc->sc_loc_shift_r, &flags, - &sc->sc_id_shift_r)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_SHIFT_R; - DPRINTFN(1, "Found right shift\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(HUP_KEYBOARD, 0xE2), - hid_input, 0, &sc->sc_loc_alt_l, &flags, - &sc->sc_id_alt_l)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_ALT_L; - DPRINTFN(1, "Found left alt\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(HUP_KEYBOARD, 0xE6), - hid_input, 0, &sc->sc_loc_alt_r, &flags, - &sc->sc_id_alt_r)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_ALT_R; - DPRINTFN(1, "Found right alt\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(HUP_KEYBOARD, 0xE3), - hid_input, 0, &sc->sc_loc_win_l, &flags, - &sc->sc_id_win_l)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_WIN_L; - DPRINTFN(1, "Found left GUI\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(HUP_KEYBOARD, 0xE7), - hid_input, 0, &sc->sc_loc_win_r, &flags, - &sc->sc_id_win_r)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_WIN_R; - DPRINTFN(1, "Found right GUI\n"); - } + /* figure out event buffer */ if (hid_locate(ptr, len, HID_USAGE2(HUP_KEYBOARD, 0x00), - hid_input, 0, &sc->sc_loc_events, &flags, - &sc->sc_id_events)) { + hid_input, 0, &sc->sc_loc_key[0], &flags, + &sc->sc_id_loc_key[0])) { if (flags & HIO_VARIABLE) { DPRINTFN(1, "Ignoring keyboard event control\n"); } else { - sc->sc_flags |= UKBD_FLAG_EVENTS; + sc->sc_loc_key_valid[0] |= 1; DPRINTFN(1, "Found keyboard event array\n"); } } + /* figure out the keys */ + for (key = 1; key != UKBD_NKEYCODE; key++) { + if (hid_locate(ptr, len, + HID_USAGE2(HUP_KEYBOARD, key), + hid_input, 0, &sc->sc_loc_key[key], &flags, + &sc->sc_id_loc_key[key])) { + if (flags & HIO_VARIABLE) { + sc->sc_loc_key_valid[key / 64] |= + 1ULL << (key % 64); + DPRINTFN(1, "Found key 0x%02x\n", key); + } + } + } + /* figure out leds on keyboard */ sc->sc_led_size = hid_report_size(ptr, len, hid_output, NULL); @@ -1301,7 +1141,7 @@ ukbd_attach(device_t dev) /* check if we should use the boot protocol */ if (usb_test_quirk(uaa, UQ_KBD_BOOTPROTO) || - (err != 0) || (!(sc->sc_flags & UKBD_FLAG_EVENTS))) { + (err != 0) || ukbd_any_key_valid(sc) == false) { DPRINTF("Forcing boot protocol\n"); @@ -1660,11 +1500,11 @@ ukbd_read(keyboard_t *kbd, int wait) ++(kbd->kb_count); #ifdef UKBD_EMULATE_ATSCANCODE - keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.modifiers); + keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.bitmap); if (keycode == NN) { return -1; } - return (ukbd_key2scan(sc, keycode, sc->sc_ndata.modifiers, + return (ukbd_key2scan(sc, keycode, sc->sc_ndata.bitmap, (usbcode & KEY_RELEASE))); #else /* !UKBD_EMULATE_ATSCANCODE */ return (usbcode); @@ -1731,13 +1571,13 @@ ukbd_read_char_locked(keyboard_t *kbd, int wait) #ifdef UKBD_EMULATE_ATSCANCODE /* USB key index -> key code -> AT scan code */ - keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.modifiers); + keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.bitmap); if (keycode == NN) { return (NOKEY); } /* return an AT scan code for the K_RAW mode */ if (sc->sc_mode == K_RAW) { - return (ukbd_key2scan(sc, keycode, sc->sc_ndata.modifiers, + return (ukbd_key2scan(sc, keycode, sc->sc_ndata.bitmap, (usbcode & KEY_RELEASE))); } #else /* !UKBD_EMULATE_ATSCANCODE */ @@ -2061,8 +1901,8 @@ ukbd_clear_state(keyboard_t *kbd) #endif memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); memset(&sc->sc_odata, 0, sizeof(sc->sc_odata)); - memset(&sc->sc_ntime, 0, sizeof(sc->sc_ntime)); - memset(&sc->sc_otime, 0, sizeof(sc->sc_otime)); + sc->sc_repeat_time = 0; + sc->sc_repeat_key = 0; } /* save the internal state, not used */ @@ -2149,11 +1989,12 @@ ukbd_set_typematic(keyboard_t *kbd, int code) #ifdef UKBD_EMULATE_ATSCANCODE static uint32_t -ukbd_atkeycode(int usbcode, int shift) +ukbd_atkeycode(int usbcode, const uint64_t *bitmap) { uint32_t keycode; keycode = ukbd_trtab[KEY_INDEX(usbcode)]; + /* * Translate Alt-PrintScreen to SysRq. * @@ -2168,13 +2009,14 @@ ukbd_atkeycode(int usbcode, int shift) * is routine. */ if ((keycode == 0x5c || keycode == 0x7e) && - shift & (MOD_ALT_L | MOD_ALT_R)) + (UKBD_KEY_PRESSED(bitmap, 0xe2 /* ALT-L */) || + UKBD_KEY_PRESSED(bitmap, 0xe6 /* ALT-R */))) return (0x54); return (keycode); } static int -ukbd_key2scan(struct ukbd_softc *sc, int code, int shift, int up) +ukbd_key2scan(struct ukbd_softc *sc, int code, const uint64_t *bitmap, int up) { static const int scan[] = { /* 89 */ @@ -2234,12 +2076,17 @@ ukbd_key2scan(struct ukbd_softc *sc, int code, int shift, int up) code = scan[code - 89]; } /* PrintScreen */ - if (code == 0x137 && (!(shift & (MOD_CONTROL_L | MOD_CONTROL_R | - MOD_SHIFT_L | MOD_SHIFT_R)))) { + if (code == 0x137 && (!( + UKBD_KEY_PRESSED(bitmap, 0xe0 /* CTRL-L */) || + UKBD_KEY_PRESSED(bitmap, 0xe4 /* CTRL-R */) || + UKBD_KEY_PRESSED(bitmap, 0xe1 /* SHIFT-L */) || + UKBD_KEY_PRESSED(bitmap, 0xe5 /* SHIFT-R */)))) { code |= SCAN_PREFIX_SHIFT; } /* Pause/Break */ - if ((code == 0x146) && (!(shift & (MOD_CONTROL_L | MOD_CONTROL_R)))) { + if ((code == 0x146) && (!( + UKBD_KEY_PRESSED(bitmap, 0xe0 /* CTRL-L */) || + UKBD_KEY_PRESSED(bitmap, 0xe4 /* CTRL-R */)))) { code = (0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL); } code |= (up ? SCAN_RELEASE : SCAN_PRESS); From fe91dd01380637ecb1ab503007a067087d7463e1 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 13 Feb 2020 16:17:05 +0000 Subject: [PATCH 07/39] addr2line: use stdbool.h header for bool Presumably a bool definition is obtained via header contamination on FreeBSD-CURRENT. Found while trying to upstream FreeBSD addr2line changes - the FreeBSD 11.2 CI build failed there. Reported by: Cirrus-CI, upstream ELF Tool Chain MFC with: r357844 Sponsored by: The FreeBSD Foundation --- contrib/elftoolchain/addr2line/addr2line.c | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/elftoolchain/addr2line/addr2line.c b/contrib/elftoolchain/addr2line/addr2line.c index 797c2a462fd3..7cd3cfb674fd 100644 --- a/contrib/elftoolchain/addr2line/addr2line.c +++ b/contrib/elftoolchain/addr2line/addr2line.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include From caab504277054b258552df23566a266d56f63e63 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 13 Feb 2020 19:03:12 +0000 Subject: [PATCH 08/39] vmm: Add Hygon Dhyana support. Submitted by: Pu Wen Discussed with: grehan Reviewed by: jhb (previous version) MFC after: 1 week Differential revision: https://reviews.freebsd.org/D23553 --- sys/amd64/vmm/io/iommu.c | 2 +- sys/amd64/vmm/vmm.c | 2 +- sys/amd64/vmm/vmm_stat.c | 2 +- sys/amd64/vmm/vmm_util.c | 5 +++-- sys/amd64/vmm/vmm_util.h | 2 +- sys/amd64/vmm/x86.c | 11 +++++++---- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c index 4c42437b5595..b9b4d0cfb16e 100644 --- a/sys/amd64/vmm/io/iommu.c +++ b/sys/amd64/vmm/io/iommu.c @@ -184,7 +184,7 @@ iommu_init(void) if (vmm_is_intel()) ops = &iommu_ops_intel; - else if (vmm_is_amd()) + else if (vmm_is_svm()) ops = &iommu_ops_amd; else ops = NULL; diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 181af6c58232..b28572b35ed9 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -347,7 +347,7 @@ vmm_init(void) if (vmm_is_intel()) ops = &vmm_ops_intel; - else if (vmm_is_amd()) + else if (vmm_is_svm()) ops = &vmm_ops_amd; else return (ENXIO); diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c index f61272c49ce4..89133d4b3868 100644 --- a/sys/amd64/vmm/vmm_stat.c +++ b/sys/amd64/vmm/vmm_stat.c @@ -67,7 +67,7 @@ vmm_stat_register(void *arg) if (vst->scope == VMM_STAT_SCOPE_INTEL && !vmm_is_intel()) return; - if (vst->scope == VMM_STAT_SCOPE_AMD && !vmm_is_amd()) + if (vst->scope == VMM_STAT_SCOPE_AMD && !vmm_is_svm()) return; if (vst_num_elems + vst->nelems >= MAX_VMM_STAT_ELEMS) { diff --git a/sys/amd64/vmm/vmm_util.c b/sys/amd64/vmm/vmm_util.c index 257854f62785..384a09d519ff 100644 --- a/sys/amd64/vmm/vmm_util.c +++ b/sys/amd64/vmm/vmm_util.c @@ -46,9 +46,10 @@ vmm_is_intel(void) } bool -vmm_is_amd(void) +vmm_is_svm(void) { - return (strcmp(cpu_vendor, "AuthenticAMD") == 0); + return (strcmp(cpu_vendor, "AuthenticAMD") == 0 || + strcmp(cpu_vendor, "HygonGenuine") == 0); } bool diff --git a/sys/amd64/vmm/vmm_util.h b/sys/amd64/vmm/vmm_util.h index 8c65e7e3a61e..ff93ce5733cc 100644 --- a/sys/amd64/vmm/vmm_util.h +++ b/sys/amd64/vmm/vmm_util.h @@ -34,7 +34,7 @@ struct trapframe; bool vmm_is_intel(void); -bool vmm_is_amd(void); +bool vmm_is_svm(void); bool vmm_supports_1G_pages(void); void dump_trapframe(struct trapframe *tf); diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c index 3164a07174d9..a45c9d3f4685 100644 --- a/sys/amd64/vmm/x86.c +++ b/sys/amd64/vmm/x86.c @@ -135,7 +135,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, break; case CPUID_8000_0008: cpuid_count(*eax, *ecx, regs); - if (vmm_is_amd()) { + if (vmm_is_svm()) { /* * As on Intel (0000_0007:0, EDX), mask out * unsupported or unsafe AMD extended features @@ -234,7 +234,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, case CPUID_8000_001D: /* AMD Cache topology, like 0000_0004 for Intel. */ - if (!vmm_is_amd()) + if (!vmm_is_svm()) goto default_leaf; /* @@ -276,8 +276,11 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, break; case CPUID_8000_001E: - /* AMD Family 16h+ additional identifiers */ - if (!vmm_is_amd() || CPUID_TO_FAMILY(cpu_id) < 0x16) + /* + * AMD Family 16h+ and Hygon Family 18h additional + * identifiers. + */ + if (!vmm_is_svm() || CPUID_TO_FAMILY(cpu_id) < 0x16) goto default_leaf; vm_get_topology(vm, &sockets, &cores, &threads, From 5a6d45d01509414353cbcadac75110b5b6c2c3e1 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 13 Feb 2020 19:05:14 +0000 Subject: [PATCH 09/39] bhyve, bhyvectl: Add Hygon Dhyana support. Submitted by: Pu Wen Reviewed by: jhb MFC after: 1 week Differential revision: https://reviews.freebsd.org/D23554 --- usr.sbin/bhyve/xmsr.c | 8 +++++--- usr.sbin/bhyvectl/bhyvectl.c | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/usr.sbin/bhyve/xmsr.c b/usr.sbin/bhyve/xmsr.c index a0f317eafbc1..0b87821836b7 100644 --- a/usr.sbin/bhyve/xmsr.c +++ b/usr.sbin/bhyve/xmsr.c @@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$"); #include "debug.h" #include "xmsr.h" -static int cpu_vendor_intel, cpu_vendor_amd; +static int cpu_vendor_intel, cpu_vendor_amd, cpu_vendor_hygon; int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t val) @@ -64,7 +64,7 @@ emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t val) default: break; } - } else if (cpu_vendor_amd) { + } else if (cpu_vendor_amd || cpu_vendor_hygon) { switch (num) { case MSR_HWCR: /* @@ -128,7 +128,7 @@ emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t *val) error = -1; break; } - } else if (cpu_vendor_amd) { + } else if (cpu_vendor_amd || cpu_vendor_hygon) { switch (num) { case MSR_BIOS_SIGN: *val = 0; @@ -225,6 +225,8 @@ init_msr(void) error = 0; if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { cpu_vendor_amd = 1; + } else if (strcmp(cpu_vendor, "HygonGenuine") == 0) { + cpu_vendor_hygon = 1; } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { cpu_vendor_intel = 1; } else { diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index dfb23c436dd5..8274e6eafccb 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -657,6 +657,8 @@ cpu_vendor_intel(void) if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { return (false); + } else if (strcmp(cpu_vendor, "HygonGenuine") == 0) { + return (false); } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { return (true); } else { From 338450436d9d691a18fb94373c58e91aa3fcb374 Mon Sep 17 00:00:00 2001 From: Li-Wen Hsu Date: Thu, 13 Feb 2020 19:05:19 +0000 Subject: [PATCH 10/39] Fix GCC build. Sponsored by: The FreeBSD Foundation --- tests/sys/net/randsleep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sys/net/randsleep.c b/tests/sys/net/randsleep.c index a602d06921e7..8bbad5b7557d 100644 --- a/tests/sys/net/randsleep.c +++ b/tests/sys/net/randsleep.c @@ -37,7 +37,7 @@ #include #include -#define RANDOM_MAX ((1<<31) - 1) +#define RANDOM_MAX (((long)1<<31) - 1) int main(int argc, char** argv){ useconds_t max_usecs, usecs; From 4afea6b4e087d9606a285bce06b20b847b7e9e50 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 13 Feb 2020 19:07:42 +0000 Subject: [PATCH 11/39] amdpm: Add Hygon Dhyana support. Submitted by: Pu Wen MFC after: 1 week Differential revision: https://reviews.freebsd.org/D23557 --- sys/dev/amdpm/amdpm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/dev/amdpm/amdpm.c b/sys/dev/amdpm/amdpm.c index 63b8fe1330ef..c1a4ee246a5d 100644 --- a/sys/dev/amdpm/amdpm.c +++ b/sys/dev/amdpm/amdpm.c @@ -67,6 +67,8 @@ static int amdpm_debug = 0; #define AMDPM_DEVICEID_AMD768PM 0x7443 #define AMDPM_DEVICEID_AMD8111PM 0x746B +#define AMDPM_VENDORID_HYGON 0x1d94 + /* nVidia nForce chipset */ #define AMDPM_VENDORID_NVIDIA 0x10de #define AMDPM_DEVICEID_NF_SMB 0x01b4 @@ -199,7 +201,8 @@ amdpm_attach(device_t dev) pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1); /* Allocate I/O space */ - if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD) + if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD || + pci_get_vendor(dev) == AMDPM_VENDORID_HYGON) amdpm_sc->rid = AMDPCI_PMBASE; else amdpm_sc->rid = NFPCI_PMBASE; From decf9c5ff61b4a53951fb065fb8139bc7859263d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 13 Feb 2020 19:09:24 +0000 Subject: [PATCH 12/39] amdsbwd, intpm: Add Hygon Dhyana support. Initialize the FCH SMBus controller for Hygon Dhyana CPU. Set the vendor of the FCH description via the exact CPU vendor. Submitted by: Pu Wen MFC after: 1 week Differential revision: https://reviews.freebsd.org/D23558 --- sys/dev/amdsbwd/amd_chipset.h | 2 ++ sys/dev/amdsbwd/amdsbwd.c | 10 ++++++++-- sys/dev/intpm/intpm.c | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sys/dev/amdsbwd/amd_chipset.h b/sys/dev/amdsbwd/amd_chipset.h index 19fe49fad38b..9d5c9d9cc0cf 100644 --- a/sys/dev/amdsbwd/amd_chipset.h +++ b/sys/dev/amdsbwd/amd_chipset.h @@ -146,3 +146,5 @@ #define AMDCZ_SMBUS_DEVID 0x790b1022 #define AMDCZ49_SMBUS_REVID 0x49 +#define HYGONCZ_SMBUS_DEVID 0x790b1d94 + diff --git a/sys/dev/amdsbwd/amdsbwd.c b/sys/dev/amdsbwd/amdsbwd.c index 00acfac69a19..e0b21c05c3dd 100644 --- a/sys/dev/amdsbwd/amdsbwd.c +++ b/sys/dev/amdsbwd/amdsbwd.c @@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include @@ -269,7 +271,8 @@ amdsbwd_identify(driver_t *driver, device_t parent) return; if (pci_get_devid(smb_dev) != AMDSB_SMBUS_DEVID && pci_get_devid(smb_dev) != AMDFCH_SMBUS_DEVID && - pci_get_devid(smb_dev) != AMDCZ_SMBUS_DEVID) + pci_get_devid(smb_dev) != AMDCZ_SMBUS_DEVID && + pci_get_devid(smb_dev) != HYGONCZ_SMBUS_DEVID) return; child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "amdsbwd", -1); @@ -378,6 +381,7 @@ static void amdsbwd_probe_fch41(device_t dev, struct resource *pmres, uint32_t *addr) { uint8_t val; + char buf[36]; val = pmio_read(pmres, AMDFCH41_PM_ISA_CTRL); if ((val & AMDFCH41_MMIO_EN) != 0) { @@ -416,7 +420,9 @@ amdsbwd_probe_fch41(device_t dev, struct resource *pmres, uint32_t *addr) amdsbwd_verbose_printf(dev, "AMDFCH41_PM_DECODE_EN3 value = %#04x\n", val); #endif - device_set_desc(dev, "AMD FCH Rev 41h+ Watchdog Timer"); + snprintf(buf, sizeof(buf), "%s FCH Rev 41h+ Watchdog Timer", + cpu_vendor_id == CPU_VENDOR_HYGON ? "Hygon" : "AMD"); + device_set_desc_copy(dev, buf); } static int diff --git a/sys/dev/intpm/intpm.c b/sys/dev/intpm/intpm.c index 5ab2249c6691..a394a8a0be73 100644 --- a/sys/dev/intpm/intpm.c +++ b/sys/dev/intpm/intpm.c @@ -102,6 +102,7 @@ const struct intsmb_device { { AMDSB_SMBUS_DEVID, "AMD SB600/7xx/8xx/9xx SMBus Controller" }, { AMDFCH_SMBUS_DEVID, "AMD FCH SMBus Controller" }, { AMDCZ_SMBUS_DEVID, "AMD FCH SMBus Controller" }, + { HYGONCZ_SMBUS_DEVID, "Hygon FCH SMBus Controller" }, }; static int @@ -243,6 +244,7 @@ intsmb_attach(device_t dev) break; case AMDFCH_SMBUS_DEVID: case AMDCZ_SMBUS_DEVID: + case HYGONCZ_SMBUS_DEVID: sc->sb8xx = 1; break; } From 100eced555110878a5910695ebfce9414e052533 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 13 Feb 2020 19:10:51 +0000 Subject: [PATCH 13/39] ecc_inject: Add Hygon Dhyana support. Submitted by: Pu Wen MFC after: 1 week Differential revision: https://reviews.freebsd.org/D23561 --- sys/dev/amd_ecc_inject/ecc_inject.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/amd_ecc_inject/ecc_inject.c b/sys/dev/amd_ecc_inject/ecc_inject.c index 7425320f8256..5021b01a8311 100644 --- a/sys/dev/amd_ecc_inject/ecc_inject.c +++ b/sys/dev/amd_ecc_inject/ecc_inject.c @@ -203,7 +203,8 @@ ecc_ei_load(void) { uint32_t val; - if (cpu_vendor_id != CPU_VENDOR_AMD || CPUID_TO_FAMILY(cpu_id) < 0x10) { + if ((cpu_vendor_id != CPU_VENDOR_AMD || CPUID_TO_FAMILY(cpu_id) < 0x10) && + cpu_vendor_id != CPU_VENDOR_HYGON) { printf("DRAM ECC error injection is not supported\n"); return (ENXIO); } From 4e012582d35afc1d896bd0abb74572f257d2c364 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 13 Feb 2020 19:12:07 +0000 Subject: [PATCH 14/39] hyperv: Add Hygon Dhyana support. Submitted by: Pu Wen MFC after: 1 week Differential revision: https://reviews.freebsd.org/D23563 --- sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c b/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c index 1c90d4bcee65..c08098138805 100644 --- a/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c +++ b/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c @@ -188,6 +188,7 @@ hyperv_tsc_tcinit(void *dummy __unused) switch (cpu_vendor_id) { case CPU_VENDOR_AMD: + case CPU_VENDOR_HYGON: hyperv_tsc_timecounter.tc_get_timecount = hyperv_tsc_timecount_mfence; tc64 = hyperv_tc64_tsc_mfence; From 43fbd654516eb5ddfa2994d92b7dfd373192796e Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 13 Feb 2020 20:23:55 +0000 Subject: [PATCH 15/39] diff: fix segfault with --tabsize and no/malformed argument --tabsize was previously listed as optional_argument, but didn't account for the optionality of it in the argument handling. This is irrelevant -- the manpage doesn't indicate that the argument is optional, and indeed there's no clear interpretation of omitting the argument because there's no other side effect of --tabsize. The "malformed" argument part of the header on this message is simply referring to usage like this: % diff --tabsize 4 A B With an optional_argument, the argument must be attached to the parameter directly (e.g. --tabsize=4), so the argument is effectively NULL with the above invocation as if no argument had been passed. PR: 243974 Submitted by: fehmi noyan isi (diff.c portion) MFC after: 3 days --- usr.bin/diff/diff.1 | 14 +++++++------- usr.bin/diff/diff.c | 2 +- usr.bin/diff/tests/diff_test.sh | 12 ++++++++++++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/usr.bin/diff/diff.1 b/usr.bin/diff/diff.1 index 47d55a4ddfc5..eb6b16f2e63d 100644 --- a/usr.bin/diff/diff.1 +++ b/usr.bin/diff/diff.1 @@ -30,7 +30,7 @@ .\" @(#)diff.1 8.1 (Berkeley) 6/30/93 .\" $FreeBSD$ .\" -.Dd February 12, 2020 +.Dd February 13, 2020 .Dt DIFF 1 .Os .Sh NAME @@ -60,7 +60,7 @@ .Op Fl -starting-file .Op Fl -speed-large-files .Op Fl -strip-trailing-cr -.Op Fl -tabsize +.Op Fl -tabsize Ar number .Op Fl -text .Op Fl -unified .Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern @@ -88,7 +88,7 @@ .Op Fl -speed-large-files .Op Fl -starting-file .Op Fl -strip-trailing-cr -.Op Fl -tabsize +.Op Fl -tabsize Ar number .Op Fl -text .Fl C Ar number | -context Ar number .Ar file1 file2 @@ -113,7 +113,7 @@ .Op Fl -speed-large-files .Op Fl -starting-file .Op Fl -strip-trailing-cr -.Op Fl -tabsize +.Op Fl -tabsize Ar number .Op Fl -text .Fl D Ar string | Fl -ifdef Ar string .Ar file1 file2 @@ -139,7 +139,7 @@ .Op Fl -speed-large-files .Op Fl -starting-file .Op Fl -strip-trailing-cr -.Op Fl -tabsize +.Op Fl -tabsize Ar number .Op Fl -text .Fl U Ar number | Fl -unified Ar number .Ar file1 file2 @@ -170,7 +170,7 @@ .Op Fl -show-c-function .Op Fl -speed-large-files .Op Fl -strip-trailing-cr -.Op Fl -tabsize +.Op Fl -tabsize Ar number .Op Fl -text .Op Fl -unidirectional-new-file .Op Fl -unified @@ -192,7 +192,7 @@ .Op Fl -no-ignore-file-name-case .Op Fl -strip-trailing-cr .Op Fl -suppress-common-lines -.Op Fl -tabsize +.Op Fl -tabsize Ar number .Op Fl -text .Op Fl -width .Fl y | Fl -side-by-side diff --git a/usr.bin/diff/diff.c b/usr.bin/diff/diff.c index e2e65e520cb5..a4e86b7855a8 100644 --- a/usr.bin/diff/diff.c +++ b/usr.bin/diff/diff.c @@ -93,7 +93,7 @@ static struct option longopts[] = { { "no-ignore-file-name-case", no_argument, NULL, OPT_NO_IGN_FN_CASE }, { "normal", no_argument, NULL, OPT_NORMAL }, { "strip-trailing-cr", no_argument, NULL, OPT_STRIPCR }, - { "tabsize", optional_argument, NULL, OPT_TSIZE }, + { "tabsize", required_argument, NULL, OPT_TSIZE }, { "changed-group-format", required_argument, NULL, OPT_CHANGED_GROUP_FORMAT}, { "suppress-common-lines", no_argument, NULL, OPT_SUPPRESS_COMMON }, { NULL, 0, 0, '\0'} diff --git a/usr.bin/diff/tests/diff_test.sh b/usr.bin/diff/tests/diff_test.sh index ba38befeccb8..b605c4733f09 100755 --- a/usr.bin/diff/tests/diff_test.sh +++ b/usr.bin/diff/tests/diff_test.sh @@ -10,6 +10,7 @@ atf_test_case side_by_side atf_test_case brief_format atf_test_case b230049 atf_test_case Bflag +atf_test_case tabsize simple_body() { @@ -164,6 +165,16 @@ Bflag_body() atf_check -s exit:1 -o file:"$(atf_get_srcdir)/Bflag_F.out" diff -B E F } +tabsize_body() +{ + printf "\tA\n" > A + printf "\tB\n" > B + + atf_check -s exit:1 \ + -o inline:"1c1\n< A\n---\n> B\n" \ + diff -t --tabsize 1 A B +} + atf_init_test_cases() { atf_add_test_case simple @@ -176,4 +187,5 @@ atf_init_test_cases() atf_add_test_case brief_format atf_add_test_case b230049 atf_add_test_case Bflag + atf_add_test_case tabsize } From a4d50e49da8e636fee461f21bf3d377be8082153 Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Thu, 13 Feb 2020 20:50:21 +0000 Subject: [PATCH 16/39] Add more precise SMR entry asserts. --- sys/kern/subr_smr.c | 9 +++++---- sys/sys/smr.h | 9 +++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sys/kern/subr_smr.c b/sys/kern/subr_smr.c index bbbc5711c499..1ea7e5d871f0 100644 --- a/sys/kern/subr_smr.c +++ b/sys/kern/subr_smr.c @@ -193,8 +193,7 @@ smr_advance(smr_t smr) /* * It is illegal to enter while in an smr section. */ - KASSERT(curthread->td_critnest == 0, - ("smr_advance: Not allowed in a critical section.")); + SMR_ASSERT_NOT_ENTERED(smr); /* * Modifications not done in a smr section need to be visible @@ -237,6 +236,8 @@ smr_advance_deferred(smr_t smr, int limit) smr_seq_t goal; smr_t csmr; + SMR_ASSERT_NOT_ENTERED(smr); + critical_enter(); csmr = zpcpu_get(smr); if (++csmr->c_deferred >= limit) { @@ -275,8 +276,8 @@ smr_poll(smr_t smr, smr_seq_t goal, bool wait) /* * It is illegal to enter while in an smr section. */ - KASSERT(!wait || curthread->td_critnest == 0, - ("smr_poll: Blocking not allowed in a critical section.")); + KASSERT(!wait || !SMR_ENTERED(smr), + ("smr_poll: Blocking not allowed in a SMR section.")); /* * Use a critical section so that we can avoid ABA races diff --git a/sys/sys/smr.h b/sys/sys/smr.h index d00f6239b884..19502020e6eb 100644 --- a/sys/sys/smr.h +++ b/sys/sys/smr.h @@ -68,6 +68,15 @@ struct smr { int c_deferred; /* Deferred advance counter. */ }; +#define SMR_ENTERED(smr) \ + (curthread->td_critnest != 0 && zpcpu_get((smr))->c_seq != SMR_SEQ_INVALID) + +#define SMR_ASSERT_ENTERED(smr) \ + KASSERT(SMR_ENTERED(smr), ("Not in smr section")) + +#define SMR_ASSERT_NOT_ENTERED(smr) \ + KASSERT(!SMR_ENTERED(smr), ("In smr section.")); + /* * Return the current write sequence number. */ From 543117bed857cfb85e3fa4d9b16df7bcba55cc52 Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Thu, 13 Feb 2020 20:58:51 +0000 Subject: [PATCH 17/39] Fix a case where ub_seq would fail to be set if the cross bucket was flushed due to memory pressure. Reviewed by: markj Differential Revision: http://reviews.freebsd.org/D23614 --- sys/vm/uma_core.c | 62 +++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 8618a620ef74..73935c966244 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -553,12 +553,13 @@ zone_fetch_bucket(uma_zone_t zone, uma_zone_domain_t zdom) if ((bucket = STAILQ_FIRST(&zdom->uzd_buckets)) == NULL) return (NULL); + /* SMR Buckets can not be re-used until readers expire. */ if ((zone->uz_flags & UMA_ZONE_SMR) != 0 && bucket->ub_seq != SMR_SEQ_INVALID) { if (!smr_poll(zone->uz_smr, bucket->ub_seq, false)) return (NULL); bucket->ub_seq = SMR_SEQ_INVALID; - dtor = (zone->uz_dtor != NULL) | UMA_ALWAYS_CTORDTOR; + dtor = (zone->uz_dtor != NULL) || UMA_ALWAYS_CTORDTOR; } MPASS(zdom->uzd_nitems >= bucket->ub_cnt); STAILQ_REMOVE_HEAD(&zdom->uzd_buckets, ub_link); @@ -678,6 +679,7 @@ cache_bucket_load(uma_cache_bucket_t bucket, uma_bucket_t b) CRITICAL_ASSERT(curthread); MPASS(bucket->ucb_bucket == NULL); + MPASS(b->ub_seq == SMR_SEQ_INVALID); bucket->ucb_bucket = b; bucket->ucb_cnt = b->ub_cnt; @@ -979,10 +981,10 @@ bucket_drain(uma_zone_t zone, uma_bucket_t bucket) if ((zone->uz_flags & UMA_ZONE_SMR) != 0 && bucket->ub_seq != SMR_SEQ_INVALID) { smr_wait(zone->uz_smr, bucket->ub_seq); + bucket->ub_seq = SMR_SEQ_INVALID; for (i = 0; i < bucket->ub_cnt; i++) item_dtor(zone, bucket->ub_bucket[i], zone->uz_size, NULL, SKIP_NONE); - bucket->ub_seq = SMR_SEQ_INVALID; } if (zone->uz_fini) for (i = 0; i < bucket->ub_cnt; i++) @@ -1014,6 +1016,7 @@ cache_drain(uma_zone_t zone) { uma_cache_t cache; uma_bucket_t bucket; + smr_seq_t seq; int cpu; /* @@ -1024,6 +1027,9 @@ cache_drain(uma_zone_t zone) * XXX: It would good to be able to assert that the zone is being * torn down to prevent improper use of cache_drain(). */ + seq = SMR_SEQ_INVALID; + if ((zone->uz_flags & UMA_ZONE_SMR) != 0) + seq = smr_current(zone->uz_smr); CPU_FOREACH(cpu) { cache = &zone->uz_cpu[cpu]; bucket = cache_bucket_unload_alloc(cache); @@ -1033,11 +1039,13 @@ cache_drain(uma_zone_t zone) } bucket = cache_bucket_unload_free(cache); if (bucket != NULL) { + bucket->ub_seq = seq; bucket_drain(zone, bucket); bucket_free(zone, bucket, NULL); } bucket = cache_bucket_unload_cross(cache); if (bucket != NULL) { + bucket->ub_seq = seq; bucket_drain(zone, bucket); bucket_free(zone, bucket, NULL); } @@ -1069,7 +1077,6 @@ cache_drain_safe_cpu(uma_zone_t zone, void *unused) return; b1 = b2 = b3 = NULL; - ZONE_LOCK(zone); critical_enter(); if (zone->uz_flags & UMA_ZONE_FIRSTTOUCH) domain = PCPU_GET(domain); @@ -1077,32 +1084,33 @@ cache_drain_safe_cpu(uma_zone_t zone, void *unused) domain = 0; cache = &zone->uz_cpu[curcpu]; b1 = cache_bucket_unload_alloc(cache); - if (b1 != NULL && b1->ub_cnt != 0) { - zone_put_bucket(zone, &zone->uz_domain[domain], b1, false); - b1 = NULL; - } /* * Don't flush SMR zone buckets. This leaves the zone without a * bucket and forces every free to synchronize(). */ - if ((zone->uz_flags & UMA_ZONE_SMR) != 0) - goto out; - b2 = cache_bucket_unload_free(cache); + if ((zone->uz_flags & UMA_ZONE_SMR) == 0) { + b2 = cache_bucket_unload_free(cache); + b3 = cache_bucket_unload_cross(cache); + } + critical_exit(); + + ZONE_LOCK(zone); + if (b1 != NULL && b1->ub_cnt != 0) { + zone_put_bucket(zone, &zone->uz_domain[domain], b1, false); + b1 = NULL; + } if (b2 != NULL && b2->ub_cnt != 0) { zone_put_bucket(zone, &zone->uz_domain[domain], b2, false); b2 = NULL; } - b3 = cache_bucket_unload_cross(cache); - -out: - critical_exit(); ZONE_UNLOCK(zone); - if (b1) + + if (b1 != NULL) bucket_free(zone, b1, NULL); - if (b2) + if (b2 != NULL) bucket_free(zone, b2, NULL); - if (b3) { + if (b3 != NULL) { bucket_drain(zone, b3); bucket_free(zone, b3, NULL); } @@ -4004,6 +4012,7 @@ zone_free_cross(uma_zone_t zone, uma_bucket_t bucket, void *udata) struct uma_bucketlist fullbuckets; uma_zone_domain_t zdom; uma_bucket_t b; + smr_seq_t seq; void *item; int domain; @@ -4019,6 +4028,14 @@ zone_free_cross(uma_zone_t zone, uma_bucket_t bucket, void *udata) * per-domain locking could be used if necessary. */ ZONE_CROSS_LOCK(zone); + + /* + * It is possible for buckets to arrive here out of order so we fetch + * the current smr seq rather than accepting the bucket's. + */ + seq = SMR_SEQ_INVALID; + if ((zone->uz_flags & UMA_ZONE_SMR) != 0) + seq = smr_current(zone->uz_smr); while (bucket->ub_cnt > 0) { item = bucket->ub_bucket[bucket->ub_cnt - 1]; domain = _vm_phys_domain(pmap_kextract((vm_offset_t)item)); @@ -4028,10 +4045,11 @@ zone_free_cross(uma_zone_t zone, uma_bucket_t bucket, void *udata) if (zdom->uzd_cross == NULL) break; } - zdom->uzd_cross->ub_bucket[zdom->uzd_cross->ub_cnt++] = item; - if (zdom->uzd_cross->ub_cnt == zdom->uzd_cross->ub_entries) { - STAILQ_INSERT_HEAD(&fullbuckets, zdom->uzd_cross, - ub_link); + b = zdom->uzd_cross; + b->ub_bucket[b->ub_cnt++] = item; + b->ub_seq = seq; + if (b->ub_cnt == b->ub_entries) { + STAILQ_INSERT_HEAD(&fullbuckets, b, ub_link); zdom->uzd_cross = NULL; } bucket->ub_cnt--; @@ -4040,8 +4058,6 @@ zone_free_cross(uma_zone_t zone, uma_bucket_t bucket, void *udata) if (!STAILQ_EMPTY(&fullbuckets)) { ZONE_LOCK(zone); while ((b = STAILQ_FIRST(&fullbuckets)) != NULL) { - if ((zone->uz_flags & UMA_ZONE_SMR) != 0) - bucket->ub_seq = smr_current(zone->uz_smr); STAILQ_REMOVE_HEAD(&fullbuckets, ub_link); if (zone->uz_bkt_count >= zone->uz_bkt_max) { ZONE_UNLOCK(zone); From 1f2a6b8501e6cc5c2828a253faabe6959c0949ca Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Thu, 13 Feb 2020 21:10:17 +0000 Subject: [PATCH 18/39] Since r357804 pcpu zones are required to use zalloc_pcpu(). Prior to this it was only required if you were zeroing. Switch to these interfaces. Reviewed by: mjg --- sys/kern/subr_smr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/kern/subr_smr.c b/sys/kern/subr_smr.c index 1ea7e5d871f0..816e68966029 100644 --- a/sys/kern/subr_smr.c +++ b/sys/kern/subr_smr.c @@ -414,7 +414,7 @@ smr_create(const char *name) int i; s = uma_zalloc(smr_shared_zone, M_WAITOK); - smr = uma_zalloc(smr_zone, M_WAITOK); + smr = uma_zalloc_pcpu(smr_zone, M_WAITOK); s->s_name = name; s->s_rd_seq = s->s_wr_seq = SMR_SEQ_INIT; @@ -436,7 +436,7 @@ smr_destroy(smr_t smr) smr_synchronize(smr); uma_zfree(smr_shared_zone, smr->c_shared); - uma_zfree(smr_zone, smr); + uma_zfree_pcpu(smr_zone, smr); } /* From 8bdcfb10d306e16a4a06592a327682e3a9f190f8 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Thu, 13 Feb 2020 22:16:02 +0000 Subject: [PATCH 19/39] Annotate suser_enabled as __read_mostly It is read a lot in priv code. --- sys/kern/kern_priv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_priv.c b/sys/kern/kern_priv.c index 98271195d9fd..a38f4f53e099 100644 --- a/sys/kern/kern_priv.c +++ b/sys/kern/kern_priv.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); * userland programs, and should not be done without careful consideration of * the consequences. */ -static int suser_enabled = 1; +static int __read_mostly suser_enabled = 1; SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RWTUN, &suser_enabled, 0, "processes with uid 0 have privilege"); From e6081fe8991b0144353365bed33cf32b91a60334 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Thu, 13 Feb 2020 22:16:30 +0000 Subject: [PATCH 20/39] Inline jailed(). It is constantly called from priv_check. --- sys/kern/kern_jail.c | 10 ---------- sys/sys/jail.h | 7 ++++++- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 8dbe2d6f5db6..17b8118f2b08 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -2820,16 +2820,6 @@ prison_ischild(struct prison *pr1, struct prison *pr2) return (0); } -/* - * Return 1 if the passed credential is in a jail, otherwise 0. - */ -int -jailed(struct ucred *cred) -{ - - return (cred->cr_prison != &prison0); -} - /* * Return 1 if the passed credential is in a jail and that jail does not * have its own virtual network stack, otherwise 0. diff --git a/sys/sys/jail.h b/sys/sys/jail.h index fa1a5f237189..f3ef5a0e5810 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -369,7 +369,12 @@ struct mount; struct sockaddr; struct statfs; struct vfsconf; -int jailed(struct ucred *cred); + +/* + * Return 1 if the passed credential is in a jail, otherwise 0. + */ +#define jailed(cred) (cred->cr_prison != &prison0) + int jailed_without_vnet(struct ucred *); void getcredhostname(struct ucred *, char *, size_t); void getcreddomainname(struct ucred *, char *, size_t); From 91061084d116fcbbcb1c1f17aad7d520b41c473b Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Thu, 13 Feb 2020 22:19:17 +0000 Subject: [PATCH 21/39] mac: implement fast path for checks All checking routines walk a linked list of all modules in order to determine if given hook is installed. This became a significant problem after mac_ntpd started being loaded by default. Implement a way perform checks for select hooks by testing a boolean. Use it for priv_check and priv_grant, which are constantly called from priv_check. The real fix would use hotpatching, but the above provides a way to know when to do it. --- sys/security/mac/mac_framework.c | 95 ++++++++++++++++++++++++++++++++ sys/security/mac/mac_framework.h | 23 +++++++- sys/security/mac/mac_priv.c | 4 +- 3 files changed, 118 insertions(+), 4 deletions(-) diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index 4a746e52d33c..1ee91d8edf94 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -117,6 +117,17 @@ static unsigned int mac_version = MAC_VERSION; SYSCTL_UINT(_security_mac, OID_AUTO, version, CTLFLAG_RD, &mac_version, 0, ""); +/* + * Flags for inlined checks. + */ +#define FPFLAG(f) \ +bool __read_frequently mac_##f##_fp_flag + +FPFLAG(priv_check); +FPFLAG(priv_grant); + +#undef FPFLAG + /* * Labels consist of a indexed set of "slots", which are allocated policies * as required. The MAC Framework maintains a bitmask of slots allocated so @@ -376,6 +387,84 @@ mac_policy_update(void) } } +/* + * There are frequently used code paths which check for rarely installed + * policies. Gross hack below enables doing it in a cheap manner. + */ + +#define FPO(f) (offsetof(struct mac_policy_ops, mpo_##f) / sizeof(uintptr_t)) + +struct mac_policy_fastpath_elem { + int count; + bool *flag; + size_t offset; +}; + +struct mac_policy_fastpath_elem mac_policy_fastpath_array[] = { + { .offset = FPO(priv_check), .flag = &mac_priv_check_fp_flag }, + { .offset = FPO(priv_grant), .flag = &mac_priv_grant_fp_flag }, +}; + +static void +mac_policy_fastpath_enable(struct mac_policy_fastpath_elem *mpfe) +{ + + MPASS(mpfe->count >= 0); + mpfe->count++; + if (mpfe->count == 1) { + MPASS(*mpfe->flag == false); + *mpfe->flag = true; + } +} + +static void +mac_policy_fastpath_disable(struct mac_policy_fastpath_elem *mpfe) +{ + + MPASS(mpfe->count >= 1); + mpfe->count--; + if (mpfe->count == 0) { + MPASS(*mpfe->flag == true); + *mpfe->flag = false; + } +} + +static void +mac_policy_fastpath_register(struct mac_policy_conf *mpc) +{ + struct mac_policy_fastpath_elem *mpfe; + uintptr_t **ops; + int i; + + mac_policy_xlock_assert(); + + ops = (uintptr_t **)mpc->mpc_ops; + for (i = 0; i < nitems(mac_policy_fastpath_array); i++) { + mpfe = &mac_policy_fastpath_array[i]; + if (ops[mpfe->offset] != NULL) + mac_policy_fastpath_enable(mpfe); + } +} + +static void +mac_policy_fastpath_unregister(struct mac_policy_conf *mpc) +{ + struct mac_policy_fastpath_elem *mpfe; + uintptr_t **ops; + int i; + + mac_policy_xlock_assert(); + + ops = (uintptr_t **)mpc->mpc_ops; + for (i = 0; i < nitems(mac_policy_fastpath_array); i++) { + mpfe = &mac_policy_fastpath_array[i]; + if (ops[mpfe->offset] != NULL) + mac_policy_fastpath_disable(mpfe); + } +} + +#undef FPO + static int mac_policy_register(struct mac_policy_conf *mpc) { @@ -446,6 +535,9 @@ mac_policy_register(struct mac_policy_conf *mpc) */ if (mpc->mpc_ops->mpo_init != NULL) (*(mpc->mpc_ops->mpo_init))(mpc); + + mac_policy_fastpath_register(mpc); + mac_policy_update(); SDT_PROBE1(mac, , policy, register, mpc); @@ -487,6 +579,9 @@ mac_policy_unregister(struct mac_policy_conf *mpc) mac_policy_xunlock(); return (EBUSY); } + + mac_policy_fastpath_unregister(mpc); + if (mpc->mpc_ops->mpo_destroy != NULL) (*(mpc->mpc_ops->mpo_destroy))(mpc); diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h index 7068d4776ff1..af35ec359e68 100644 --- a/sys/security/mac/mac_framework.h +++ b/sys/security/mac/mac_framework.h @@ -258,8 +258,27 @@ void mac_posixshm_create(struct ucred *cred, struct shmfd *shmfd); void mac_posixshm_destroy(struct shmfd *); void mac_posixshm_init(struct shmfd *); -int mac_priv_check(struct ucred *cred, int priv); -int mac_priv_grant(struct ucred *cred, int priv); +int mac_priv_check_impl(struct ucred *cred, int priv); +extern bool mac_priv_check_fp_flag; +static inline int +mac_priv_check(struct ucred *cred, int priv) +{ + + if (__predict_false(mac_priv_check_fp_flag)) + return (mac_priv_check_impl(cred, priv)); + return (0); +} + +int mac_priv_grant_impl(struct ucred *cred, int priv); +extern bool mac_priv_grant_fp_flag; +static inline int +mac_priv_grant(struct ucred *cred, int priv) +{ + + if (__predict_false(mac_priv_grant_fp_flag)) + return (mac_priv_grant_impl(cred, priv)); + return (EPERM); +} int mac_proc_check_debug(struct ucred *cred, struct proc *p); int mac_proc_check_sched(struct ucred *cred, struct proc *p); diff --git a/sys/security/mac/mac_priv.c b/sys/security/mac/mac_priv.c index 5d39568ccc4f..b4537e7cbe21 100644 --- a/sys/security/mac/mac_priv.c +++ b/sys/security/mac/mac_priv.c @@ -67,7 +67,7 @@ MAC_CHECK_PROBE_DEFINE2(priv_check, "struct ucred *", "int"); * policy denies access. */ int -mac_priv_check(struct ucred *cred, int priv) +mac_priv_check_impl(struct ucred *cred, int priv) { int error; @@ -84,7 +84,7 @@ MAC_GRANT_PROBE_DEFINE2(priv_grant, "struct ucred *", "int"); * policy grants access. */ int -mac_priv_grant(struct ucred *cred, int priv) +mac_priv_grant_impl(struct ucred *cred, int priv) { int error; From 7b2ff0dcb25355f47ee1967010d29765e021f503 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Thu, 13 Feb 2020 22:22:15 +0000 Subject: [PATCH 22/39] Partially decompose priv_check by adding priv_check_cred_vfs_generation During buildkernel there are very frequent calls to priv_check and they all are for PRIV_VFS_GENERATION (coming from stat/fstat). This results in branching on several potential privileges checking if perhaps that's the one which has to be evaluated. Instead of the kitchen-sink approach provide a way to have commonly used privs directly evaluated. --- sys/kern/kern_jail.c | 10 ++++ sys/kern/kern_priv.c | 104 ++++++++++++++++++++++++++++++---------- sys/kern/vfs_syscalls.c | 4 +- sys/kern/vfs_vnops.c | 2 +- sys/sys/priv.h | 1 + 5 files changed, 92 insertions(+), 29 deletions(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 17b8118f2b08..222d36e2b268 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -2998,6 +2998,16 @@ int prison_priv_check(struct ucred *cred, int priv) { + /* + * Some policies have custom handlers. This routine should not be + * called for them. See priv_check_cred(). + */ + switch (priv) { + case PRIV_VFS_GENERATION: + KASSERT(0, ("prison_priv_check instead of a custom handler " + "called for %d\n", priv)); + } + if (!jailed(cred)) return (0); diff --git a/sys/kern/kern_priv.c b/sys/kern/kern_priv.c index a38f4f53e099..58ce6cf342a5 100644 --- a/sys/kern/kern_priv.c +++ b/sys/kern/kern_priv.c @@ -71,6 +71,51 @@ SDT_PROVIDER_DEFINE(priv); SDT_PROBE_DEFINE1(priv, kernel, priv_check, priv__ok, "int"); SDT_PROBE_DEFINE1(priv, kernel, priv_check, priv__err, "int"); +static __always_inline int +priv_check_cred_pre(struct ucred *cred, int priv) +{ + int error; + +#ifdef MAC + error = mac_priv_check(cred, priv); +#else + error = 0; +#endif + return (error); +} + +static __always_inline int +priv_check_cred_post(struct ucred *cred, int priv, int error, bool handled) +{ + + if (__predict_true(handled)) + goto out; + /* + * Now check with MAC, if enabled, to see if a policy module grants + * privilege. + */ +#ifdef MAC + if (mac_priv_grant(cred, priv) == 0) { + error = 0; + goto out; + } +#endif + + /* + * The default is deny, so if no policies have granted it, reject + * with a privilege error here. + */ + error = EPERM; +out: + if (SDT_PROBES_ENABLED()) { + if (error) + SDT_PROBE1(priv, kernel, priv_check, priv__err, priv); + else + SDT_PROBE1(priv, kernel, priv_check, priv__ok, priv); + } + return (error); +} + /* * Check a credential for privilege. Lots of good reasons to deny privilege; * only a few to grant it. @@ -83,15 +128,18 @@ priv_check_cred(struct ucred *cred, int priv) KASSERT(PRIV_VALID(priv), ("priv_check_cred: invalid privilege %d", priv)); + switch (priv) { + case PRIV_VFS_GENERATION: + return (priv_check_cred_vfs_generation(cred)); + } + /* * We first evaluate policies that may deny the granting of * privilege unilaterally. */ -#ifdef MAC - error = mac_priv_check(cred, priv); + error = priv_check_cred_pre(cred, priv); if (error) goto out; -#endif /* * Jail policy will restrict certain privileges that may otherwise be @@ -177,30 +225,9 @@ priv_check_cred(struct ucred *cred, int priv) } } - /* - * Now check with MAC, if enabled, to see if a policy module grants - * privilege. - */ -#ifdef MAC - if (mac_priv_grant(cred, priv) == 0) { - error = 0; - goto out; - } -#endif - - /* - * The default is deny, so if no policies have granted it, reject - * with a privilege error here. - */ - error = EPERM; + return (priv_check_cred_post(cred, priv, error, false)); out: - if (SDT_PROBES_ENABLED()) { - if (error) - SDT_PROBE1(priv, kernel, priv_check, priv__err, priv); - else - SDT_PROBE1(priv, kernel, priv_check, priv__ok, priv); - } - return (error); + return (priv_check_cred_post(cred, priv, error, true)); } int @@ -211,3 +238,28 @@ priv_check(struct thread *td, int priv) return (priv_check_cred(td->td_ucred, priv)); } + +int +priv_check_cred_vfs_generation(struct ucred *cred) +{ + int error; + + error = priv_check_cred_pre(cred, PRIV_VFS_GENERATION); + if (error) + goto out; + + if (jailed(cred)) { + error = EPERM; + goto out; + } + + if (cred->cr_uid == 0 && suser_enabled) { + error = 0; + goto out; + } + + return (priv_check_cred_post(cred, PRIV_VFS_GENERATION, error, false)); +out: + return (priv_check_cred_post(cred, PRIV_VFS_GENERATION, error, true)); + +} diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index a77018a778aa..162051f666b4 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -273,7 +273,7 @@ kern_do_statfs(struct thread *td, struct mount *mp, struct statfs *buf) error = VFS_STATFS(mp, buf); if (error != 0) goto out; - if (priv_check(td, PRIV_VFS_GENERATION)) { + if (priv_check_cred_vfs_generation(td->td_ucred)) { buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, buf); } @@ -488,7 +488,7 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, continue; } } - if (priv_check(td, PRIV_VFS_GENERATION)) { + if (priv_check_cred_vfs_generation(td->td_ucred)) { sptmp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); *sptmp = *sp; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 2235b4f022e3..b6748de8a8d9 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1477,7 +1477,7 @@ vn_stat(struct vnode *vp, struct stat *sb, struct ucred *active_cred, sb->st_blksize = max(PAGE_SIZE, vap->va_blocksize); sb->st_flags = vap->va_flags; - if (priv_check(td, PRIV_VFS_GENERATION)) + if (priv_check_cred_vfs_generation(td->td_ucred)) sb->st_gen = 0; else sb->st_gen = vap->va_gen; diff --git a/sys/sys/priv.h b/sys/sys/priv.h index acf50903974c..7529231e3e2b 100644 --- a/sys/sys/priv.h +++ b/sys/sys/priv.h @@ -533,6 +533,7 @@ struct thread; struct ucred; int priv_check(struct thread *td, int priv); int priv_check_cred(struct ucred *cred, int priv); +int priv_check_cred_vfs_generation(struct ucred *cred); #endif #endif /* !_SYS_PRIV_H_ */ From 6ebab6bad21479981246758a82540fd4cc76f678 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Thu, 13 Feb 2020 22:22:55 +0000 Subject: [PATCH 23/39] vfs: use mac fastpath for lookup, open, read, write, mmap --- sys/kern/vfs_lookup.c | 9 +-- sys/security/mac/mac_framework.c | 18 ++++++ sys/security/mac/mac_framework.h | 98 +++++++++++++++++++++++++++++--- sys/security/mac/mac_vfs.c | 23 ++++++-- 4 files changed, 127 insertions(+), 21 deletions(-) diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index c8c303347010..dd4157265268 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -932,12 +932,9 @@ lookup(struct nameidata *ndp) */ unionlookup: #ifdef MAC - if ((cnp->cn_flags & NOMACCHECK) == 0) { - error = mac_vnode_check_lookup(cnp->cn_thread->td_ucred, dp, - cnp); - if (error) - goto bad; - } + error = mac_vnode_check_lookup(cnp->cn_thread->td_ucred, dp, cnp); + if (error) + goto bad; #endif ndp->ni_dvp = dp; ndp->ni_vp = NULL; diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index 1ee91d8edf94..e11bf12648a3 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -125,6 +125,12 @@ bool __read_frequently mac_##f##_fp_flag FPFLAG(priv_check); FPFLAG(priv_grant); +FPFLAG(vnode_check_lookup); +FPFLAG(vnode_check_open); +FPFLAG(vnode_check_stat); +FPFLAG(vnode_check_read); +FPFLAG(vnode_check_write); +FPFLAG(vnode_check_mmap); #undef FPFLAG @@ -403,6 +409,18 @@ struct mac_policy_fastpath_elem { struct mac_policy_fastpath_elem mac_policy_fastpath_array[] = { { .offset = FPO(priv_check), .flag = &mac_priv_check_fp_flag }, { .offset = FPO(priv_grant), .flag = &mac_priv_grant_fp_flag }, + { .offset = FPO(vnode_check_lookup), + .flag = &mac_vnode_check_lookup_fp_flag }, + { .offset = FPO(vnode_check_open), + .flag = &mac_vnode_check_open_fp_flag }, + { .offset = FPO(vnode_check_stat), + .flag = &mac_vnode_check_stat_fp_flag }, + { .offset = FPO(vnode_check_read), + .flag = &mac_vnode_check_read_fp_flag }, + { .offset = FPO(vnode_check_write), + .flag = &mac_vnode_check_write_fp_flag }, + { .offset = FPO(vnode_check_mmap), + .flag = &mac_vnode_check_mmap_fp_flag }, }; static void diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h index af35ec359e68..66f0ab90b293 100644 --- a/sys/security/mac/mac_framework.h +++ b/sys/security/mac/mac_framework.h @@ -390,6 +390,12 @@ void mac_sysvshm_init(struct shmid_kernel *); void mac_thread_userret(struct thread *td); +#ifdef DEBUG_VFS_LOCKS +void mac_vnode_assert_locked(struct vnode *vp, const char *func); +#else +#define mac_vnode_assert_locked(vp, func) do { } while (0) +#endif + int mac_vnode_associate_extattr(struct mount *mp, struct vnode *vp); void mac_vnode_associate_singlelabel(struct mount *mp, struct vnode *vp); int mac_vnode_check_access(struct ucred *cred, struct vnode *vp, @@ -412,18 +418,53 @@ int mac_vnode_check_link(struct ucred *cred, struct vnode *dvp, struct vnode *vp, struct componentname *cnp); int mac_vnode_check_listextattr(struct ucred *cred, struct vnode *vp, int attrnamespace); -int mac_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, + +int mac_vnode_check_lookup_impl(struct ucred *cred, struct vnode *dvp, struct componentname *cnp); -int mac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, int prot, +extern bool mac_vnode_check_lookup_fp_flag; +static inline int +mac_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, + struct componentname *cnp) +{ + + mac_vnode_assert_locked(dvp, "mac_vnode_check_lookup"); + if (__predict_false(mac_vnode_check_lookup_fp_flag)) + return (mac_vnode_check_lookup_impl(cred, dvp, cnp)); + return (0); +} + +int mac_vnode_check_mmap_impl(struct ucred *cred, struct vnode *vp, int prot, int flags); +extern bool mac_vnode_check_mmap_fp_flag; +static inline int +mac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, int prot, + int flags) +{ + + mac_vnode_assert_locked(vp, "mac_vnode_check_mmap"); + if (__predict_false(mac_vnode_check_mmap_fp_flag)) + return (mac_vnode_check_mmap_impl(cred, vp, prot, flags)); + return (0); +} + +int mac_vnode_check_open_impl(struct ucred *cred, struct vnode *vp, + accmode_t accmode); +extern bool mac_vnode_check_open_fp_flag; +static inline int +mac_vnode_check_open(struct ucred *cred, struct vnode *vp, + accmode_t accmode) +{ + + mac_vnode_assert_locked(vp, "mac_vnode_check_open"); + if (__predict_false(mac_vnode_check_open_fp_flag)) + return (mac_vnode_check_open_impl(cred, vp, accmode)); + return (0); +} + int mac_vnode_check_mprotect(struct ucred *cred, struct vnode *vp, int prot); -int mac_vnode_check_open(struct ucred *cred, struct vnode *vp, - accmode_t accmode); int mac_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp); -int mac_vnode_check_read(struct ucred *active_cred, - struct ucred *file_cred, struct vnode *vp); int mac_vnode_check_readdir(struct ucred *cred, struct vnode *vp); int mac_vnode_check_readlink(struct ucred *cred, struct vnode *vp); int mac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, @@ -443,12 +484,51 @@ int mac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, gid_t gid); int mac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, struct timespec atime, struct timespec mtime); -int mac_vnode_check_stat(struct ucred *active_cred, + +int mac_vnode_check_stat_impl(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp); +extern bool mac_vnode_check_stat_fp_flag; +static inline int +mac_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred, + struct vnode *vp) +{ + + mac_vnode_assert_locked(vp, "mac_vnode_check_stat"); + if (__predict_false(mac_vnode_check_stat_fp_flag)) + return (mac_vnode_check_stat_impl(active_cred, file_cred, vp)); + return (0); +} + +int mac_vnode_check_read_impl(struct ucred *active_cred, + struct ucred *file_cred, struct vnode *vp); +extern bool mac_vnode_check_read_fp_flag; +static inline int +mac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred, + struct vnode *vp) +{ + + mac_vnode_assert_locked(vp, "mac_vnode_check_read"); + if (__predict_false(mac_vnode_check_read_fp_flag)) + return (mac_vnode_check_read_impl(active_cred, file_cred, vp)); + return (0); +} + +int mac_vnode_check_write_impl(struct ucred *active_cred, + struct ucred *file_cred, struct vnode *vp); +extern bool mac_vnode_check_write_fp_flag; +static inline int +mac_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred, + struct vnode *vp) +{ + + mac_vnode_assert_locked(vp, "mac_vnode_check_write"); + if (__predict_false(mac_vnode_check_write_fp_flag)) + return (mac_vnode_check_write_impl(active_cred, file_cred, vp)); + return (0); +} + int mac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, struct vnode *vp, struct componentname *cnp); -int mac_vnode_check_write(struct ucred *active_cred, - struct ucred *file_cred, struct vnode *vp); void mac_vnode_copy_label(struct label *, struct label *); void mac_vnode_init(struct vnode *); int mac_vnode_create_extattr(struct ucred *cred, struct mount *mp, diff --git a/sys/security/mac/mac_vfs.c b/sys/security/mac/mac_vfs.c index 1d08f61b1a18..7b8489d48103 100644 --- a/sys/security/mac/mac_vfs.c +++ b/sys/security/mac/mac_vfs.c @@ -565,13 +565,15 @@ MAC_CHECK_PROBE_DEFINE3(vnode_check_lookup, "struct ucred *", "struct vnode *", "struct componentname *"); int -mac_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, +mac_vnode_check_lookup_impl(struct ucred *cred, struct vnode *dvp, struct componentname *cnp) { int error; ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_lookup"); + if ((cnp->cn_flags & NOMACCHECK) != 0) + return (0); MAC_POLICY_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp); MAC_CHECK_PROBE3(vnode_check_lookup, error, cred, dvp, cnp); @@ -582,7 +584,7 @@ MAC_CHECK_PROBE_DEFINE4(vnode_check_mmap, "struct ucred *", "struct vnode *", "int", "int"); int -mac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, int prot, +mac_vnode_check_mmap_impl(struct ucred *cred, struct vnode *vp, int prot, int flags) { int error; @@ -629,7 +631,7 @@ MAC_CHECK_PROBE_DEFINE3(vnode_check_open, "struct ucred *", "struct vnode *", "accmode_t"); int -mac_vnode_check_open(struct ucred *cred, struct vnode *vp, accmode_t accmode) +mac_vnode_check_open_impl(struct ucred *cred, struct vnode *vp, accmode_t accmode) { int error; @@ -664,7 +666,7 @@ MAC_CHECK_PROBE_DEFINE3(vnode_check_read, "struct ucred *", "struct ucred *", "struct vnode *"); int -mac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred, +mac_vnode_check_read_impl(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp) { int error; @@ -889,7 +891,7 @@ MAC_CHECK_PROBE_DEFINE3(vnode_check_stat, "struct ucred *", "struct ucred *", "struct vnode *"); int -mac_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred, +mac_vnode_check_stat_impl(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp) { int error; @@ -927,7 +929,7 @@ MAC_CHECK_PROBE_DEFINE3(vnode_check_write, "struct ucred *", "struct ucred *", "struct vnode *"); int -mac_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred, +mac_vnode_check_write_impl(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp) { int error; @@ -1068,3 +1070,12 @@ vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) return (0); } + +#ifdef DEBUG_VFS_LOCKS +void +mac_vnode_assert_locked(struct vnode *vp, const char *func) +{ + + ASSERT_VOP_LOCKED(vp, func); +} +#endif From ca3b3c573ee0e39ca185974731424f1263082cf7 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 13 Feb 2020 22:55:45 +0000 Subject: [PATCH 24/39] Remove the per-TXQ tls_wrs stat. It duplicated the kern_tls_records stat and was not conditional on NIC TLS being enabled. Reviewed by: np Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D23670 --- sys/dev/cxgbe/adapter.h | 1 - sys/dev/cxgbe/crypto/t4_kern_tls.c | 1 - sys/dev/cxgbe/t4_main.c | 1 - sys/dev/cxgbe/t4_sge.c | 2 -- 4 files changed, 5 deletions(-) diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index 6a9e86a51225..c2cef9aa531a 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -574,7 +574,6 @@ struct sge_txq { uint64_t txpkts0_pkts; /* # of frames in type0 coalesced tx WRs */ uint64_t txpkts1_pkts; /* # of frames in type1 coalesced tx WRs */ uint64_t raw_wrs; /* # of raw work requests (alloc_wr_mbuf) */ - uint64_t tls_wrs; /* # of TLS work requests */ uint64_t kern_tls_records; uint64_t kern_tls_short; diff --git a/sys/dev/cxgbe/crypto/t4_kern_tls.c b/sys/dev/cxgbe/crypto/t4_kern_tls.c index e4a261c63b1e..b79ff3c3d552 100644 --- a/sys/dev/cxgbe/crypto/t4_kern_tls.c +++ b/sys/dev/cxgbe/crypto/t4_kern_tls.c @@ -2082,7 +2082,6 @@ ktls_write_tls_wr(struct tlspcb *tlsp, struct sge_txq *txq, ndesc += howmany(wr_len, EQ_ESIZE); MPASS(ndesc <= available); - txq->tls_wrs++; txq->kern_tls_records++; txq->kern_tls_octets += tlen - mtod(m_tls, vm_offset_t); diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 48263bf5fef7..f0de51aa1580 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -10359,7 +10359,6 @@ clear_stats(struct adapter *sc, u_int port_id) txq->txpkts0_pkts = 0; txq->txpkts1_pkts = 0; txq->raw_wrs = 0; - txq->tls_wrs = 0; txq->kern_tls_records = 0; txq->kern_tls_short = 0; txq->kern_tls_partial = 0; diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 3a144ae817ff..c5e967998f60 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -4204,8 +4204,6 @@ alloc_txq(struct vi_info *vi, struct sge_txq *txq, int idx, "# of frames tx'd using type1 txpkts work requests"); SYSCTL_ADD_UQUAD(&vi->ctx, children, OID_AUTO, "raw_wrs", CTLFLAG_RD, &txq->raw_wrs, "# of raw work requests (non-packets)"); - SYSCTL_ADD_UQUAD(&vi->ctx, children, OID_AUTO, "tls_wrs", CTLFLAG_RD, - &txq->tls_wrs, "# of TLS work requests (TLS records)"); #ifdef KERN_TLS if (sc->flags & KERN_TLS_OK) { From ff8c6681c89280edf48a2dfaca777b117842ef59 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 13 Feb 2020 23:04:11 +0000 Subject: [PATCH 25/39] Don't check the auth algorithm for GCM. The upstream OpenSSL changes only set the cipher for GCM since the authentication is redundant, and changes to OCF will soon remove the GCM authentication algorithm constants entirely for the same reason. In addition, ktls_create_session() already validates these fields and wouldn't pass down an invalid auth_algorithm value to any drivers or ktls backends. Reviewed by: hselasky Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D23671 --- sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c index 70e442489d3b..3ac35540368f 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c @@ -339,10 +339,6 @@ mlx5e_tls_snd_tag_alloc(struct ifnet *ifp, case CRYPTO_AES_NIST_GCM_16: switch (en->cipher_key_len) { case 128 / 8: - if (en->auth_algorithm != CRYPTO_AES_128_NIST_GMAC) { - error = EINVAL; - goto failure; - } if (en->tls_vminor == TLS_MINOR_VER_TWO) { if (MLX5_CAP_TLS(priv->mdev, tls_1_2_aes_gcm_128) == 0) { error = EPROTONOSUPPORT; @@ -360,10 +356,6 @@ mlx5e_tls_snd_tag_alloc(struct ifnet *ifp, break; case 256 / 8: - if (en->auth_algorithm != CRYPTO_AES_256_NIST_GMAC) { - error = EINVAL; - goto failure; - } if (en->tls_vminor == TLS_MINOR_VER_TWO) { if (MLX5_CAP_TLS(priv->mdev, tls_1_2_aes_gcm_256) == 0) { error = EPROTONOSUPPORT; From cefc92e1a2beaa7077e4b363e034797505f6c4cd Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Thu, 13 Feb 2020 23:15:21 +0000 Subject: [PATCH 26/39] Update the zone-global count of cached items in bucket_cache_reclaim(). This was missed in r351673. The count is used to enfore cache limits, which are rarely used. Discussed with: jeff Sponsored by: The FreeBSD Foundation --- sys/vm/uma_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 73935c966244..331a04434ccf 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -1204,6 +1204,7 @@ bucket_cache_reclaim(uma_zone_t zone, bool drain) tofree = bucket->ub_cnt; STAILQ_REMOVE_HEAD(&zdom->uzd_buckets, ub_link); zdom->uzd_nitems -= tofree; + zone->uz_bkt_count -= tofree; /* * Shift the bounds of the current WSS interval to avoid From 06ef60525f8ebcc171e5eb4d369200f5491f66a8 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Thu, 13 Feb 2020 23:18:35 +0000 Subject: [PATCH 27/39] Fix handling of WAITFAIL in vm_page_grab() and vm_page_grab_pages(). After sleeping through a memory shortage, we must return NULL rather than retry. Discussed with: jeff Reported by: pho Sponsored by: The FreeBSD Foundation --- sys/vm/vm_page.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 574c28384c61..087604d534ae 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -4258,7 +4258,7 @@ vm_page_grab(vm_object_t object, vm_pindex_t pindex, int allocflags) return (NULL); m = vm_page_alloc(object, pindex, pflags); if (m == NULL) { - if ((allocflags & VM_ALLOC_NOWAIT) != 0) + if ((allocflags & (VM_ALLOC_NOWAIT | VM_ALLOC_WAITFAIL)) != 0) return (NULL); goto retrylookup; } @@ -4466,7 +4466,8 @@ vm_page_grab_pages(vm_object_t object, vm_pindex_t pindex, int allocflags, m = vm_page_alloc_after(object, pindex + i, pflags | VM_ALLOC_COUNT(count - i), mpred); if (m == NULL) { - if ((allocflags & VM_ALLOC_NOWAIT) != 0) + if ((allocflags & (VM_ALLOC_NOWAIT | + VM_ALLOC_WAITFAIL)) != 0) break; goto retrylookup; } From 751fae1effde32b441dd232a0bf3340a419f2d17 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 13 Feb 2020 23:22:12 +0000 Subject: [PATCH 28/39] Return success, instead of ESRCH, from pthread_cancel(3) applied to the exited but not yet joined thread. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before, if the thread exited but was not yet joined, we returned ESRCH. According to IEEE Std 1003.1™-2017 recommendation in the description of pthread_cancel(3): If an implementation detects use of a thread ID after the end of its lifetime, it is recommended that the function should fail and report an [ESRCH] error. So it seems desirable to not return ESRCH until the lifetime of the thread ID ends. According to the section 2.9.2 Thread IDs, The lifetime of a thread ID ends after the thread terminates if it was created with the detachstate attribute set to PTHREAD_CREATE_DETACHED or if pthread_detach() or pthread_join() has been called for that thread. In other words, lifetime for thread ID of exited but not yet joined thread did not ended yet. Prompted by: cperciva Sponsored by: The FreeBSD Foundation MFC after: 1 week --- lib/libthr/thread/thr_cancel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libthr/thread/thr_cancel.c b/lib/libthr/thread/thr_cancel.c index 4194fe180565..7e78fe9163c7 100644 --- a/lib/libthr/thread/thr_cancel.c +++ b/lib/libthr/thread/thr_cancel.c @@ -71,7 +71,7 @@ _thr_cancel(pthread_t pthread) * _thr_find_thread and THR_THREAD_UNLOCK will enter and leave critical * region automatically. */ - if ((ret = _thr_find_thread(curthread, pthread, 0)) == 0) { + if ((ret = _thr_find_thread(curthread, pthread, 1)) == 0) { if (!pthread->cancel_pending) { pthread->cancel_pending = 1; if (pthread->state != PS_DEAD) From c5ca0d11329ba710dd039720d5ff37401f9b2222 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 13 Feb 2020 23:42:09 +0000 Subject: [PATCH 29/39] Handle non-plt IRELATIVE relocations, at least for x86. lld 10.0 seems to generate this relocation for rdtsc_mb() ifunc in our libc. Reported, reviewed, and tested by: dim (amd64, previous version) Discussed with: emaste Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D23652 --- libexec/rtld-elf/aarch64/reloc.c | 52 ++++++++++++++++------ libexec/rtld-elf/amd64/reloc.c | 69 ++++++++++++++++++++---------- libexec/rtld-elf/arm/reloc.c | 9 ++++ libexec/rtld-elf/i386/reloc.c | 61 ++++++++++++++++++-------- libexec/rtld-elf/mips/reloc.c | 9 ++++ libexec/rtld-elf/powerpc/reloc.c | 7 +++ libexec/rtld-elf/powerpc64/reloc.c | 7 +++ libexec/rtld-elf/riscv/reloc.c | 9 ++++ libexec/rtld-elf/rtld.c | 5 ++- libexec/rtld-elf/rtld.h | 2 + libexec/rtld-elf/sparc64/reloc.c | 9 ++++ 11 files changed, 185 insertions(+), 54 deletions(-) diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c index f1c66816fcee..073c0dfaf1a2 100644 --- a/libexec/rtld-elf/aarch64/reloc.c +++ b/libexec/rtld-elf/aarch64/reloc.c @@ -258,27 +258,52 @@ reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) return (0); } +static void +reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela, + RtldLockState *lockstate) +{ + Elf_Addr *where, target, *ptr; + + ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + lock_release(rtld_bind_lock, lockstate); + target = call_ifunc_resolver(ptr); + wlock_acquire(rtld_bind_lock, lockstate); + *where = target; +} + int reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate) { const Elf_Rela *relalim; const Elf_Rela *rela; - Elf_Addr *where, target, *ptr; if (!obj->irelative) return (0); - relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); - for (rela = obj->pltrela; rela < relalim; rela++) { - if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE) { - ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); - where = (Elf_Addr *)(obj->relocbase + rela->r_offset); - lock_release(rtld_bind_lock, lockstate); - target = call_ifunc_resolver(ptr); - wlock_acquire(rtld_bind_lock, lockstate); - *where = target; - } - } obj->irelative = false; + relalim = (const Elf_Rela *)((const char *)obj->pltrela + + obj->pltrelasize); + for (rela = obj->pltrela; rela < relalim; rela++) { + if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE) + reloc_iresolve_one(obj, rela, lockstate); + } + return (0); +} + +int +reloc_iresolve_nonplt(Obj_Entry *obj, struct Struct_RtldLockState *lockstate) +{ + const Elf_Rela *relalim; + const Elf_Rela *rela; + + if (!obj->irelative_nonplt) + return (0); + obj->irelative_nonplt = false; + relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); + for (rela = obj->rela; rela < relalim; rela++) { + if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE) + reloc_iresolve_one(obj, rela, lockstate); + } return (0); } @@ -498,6 +523,9 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, break; case R_AARCH64_NONE: break; + case R_AARCH64_IRELATIVE: + obj->irelative_nonplt = true; + break; default: rtld_printf("%s: Unhandled relocation %lu\n", obj->path, ELF_R_TYPE(rela->r_info)); diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c index c88f98a1835b..ae15f6a41dec 100644 --- a/libexec/rtld-elf/amd64/reloc.c +++ b/libexec/rtld-elf/amd64/reloc.c @@ -303,6 +303,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, case R_X86_64_RELATIVE: *where = (Elf_Addr)(obj->relocbase + rela->r_addend); break; + case R_X86_64_IRELATIVE: + obj->irelative_nonplt = true; + break; + /* * missing: * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16, @@ -410,34 +414,53 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, return (target); } +static void +reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela, + RtldLockState *lockstate) +{ + Elf_Addr *where, target, *ptr; + + ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + lock_release(rtld_bind_lock, lockstate); + target = call_ifunc_resolver(ptr); + wlock_acquire(rtld_bind_lock, lockstate); + *where = target; +} + int reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate) { - const Elf_Rela *relalim; - const Elf_Rela *rela; + const Elf_Rela *relalim; + const Elf_Rela *rela; - if (!obj->irelative) - return (0); - relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); - for (rela = obj->pltrela; rela < relalim; rela++) { - Elf_Addr *where, target, *ptr; - - switch (ELF_R_TYPE(rela->r_info)) { - case R_X86_64_JMP_SLOT: - break; - - case R_X86_64_IRELATIVE: - ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); - where = (Elf_Addr *)(obj->relocbase + rela->r_offset); - lock_release(rtld_bind_lock, lockstate); - target = call_ifunc_resolver(ptr); - wlock_acquire(rtld_bind_lock, lockstate); - *where = target; - break; + if (!obj->irelative) + return (0); + obj->irelative = false; + relalim = (const Elf_Rela *)((const char *)obj->pltrela + + obj->pltrelasize); + for (rela = obj->pltrela; rela < relalim; rela++) { + if (ELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE) + reloc_iresolve_one(obj, rela, lockstate); } - } - obj->irelative = false; - return (0); + return (0); +} + +int +reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate) +{ + const Elf_Rela *relalim; + const Elf_Rela *rela; + + if (!obj->irelative_nonplt) + return (0); + obj->irelative_nonplt = false; + relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); + for (rela = obj->rela; rela < relalim; rela++) { + if (ELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE) + reloc_iresolve_one(obj, rela, lockstate); + } + return (0); } int diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c index 09213413f66d..d389bb0f8e87 100644 --- a/libexec/rtld-elf/arm/reloc.c +++ b/libexec/rtld-elf/arm/reloc.c @@ -451,6 +451,15 @@ reloc_iresolve(Obj_Entry *obj __unused, return (0); } +int +reloc_iresolve_nonplt(Obj_Entry *obj __unused, + struct Struct_RtldLockState *lockstate __unused) +{ + + /* XXX not implemented */ + return (0); +} + int reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, struct Struct_RtldLockState *lockstate __unused) diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c index ef6e805aeeb4..7f2dd0c69ef1 100644 --- a/libexec/rtld-elf/i386/reloc.c +++ b/libexec/rtld-elf/i386/reloc.c @@ -263,6 +263,9 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, case R_386_TLS_DTPOFF32: *where += (Elf_Addr) def->st_value; break; + case R_386_IRELATIVE: + obj->irelative_nonplt = true; + break; default: _rtld_error("%s: Unsupported relocation type %d" " in non-PLT relocations\n", obj->path, @@ -365,29 +368,51 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, return (target); } +static void +reloc_iresolve_one(Obj_Entry *obj, const Elf_Rel *rel, + RtldLockState *lockstate) +{ + Elf_Addr *where, target; + + where = (Elf_Addr *)(obj->relocbase + rel->r_offset); + lock_release(rtld_bind_lock, lockstate); + target = call_ifunc_resolver(obj->relocbase + *where); + wlock_acquire(rtld_bind_lock, lockstate); + *where = target; +} + int reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate) { - const Elf_Rel *rellim; - const Elf_Rel *rel; - Elf_Addr *where, target; + const Elf_Rel *rellim; + const Elf_Rel *rel; - if (!obj->irelative) - return (0); - rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize); - for (rel = obj->pltrel; rel < rellim; rel++) { - switch (ELF_R_TYPE(rel->r_info)) { - case R_386_IRELATIVE: - where = (Elf_Addr *)(obj->relocbase + rel->r_offset); - lock_release(rtld_bind_lock, lockstate); - target = call_ifunc_resolver(obj->relocbase + *where); - wlock_acquire(rtld_bind_lock, lockstate); - *where = target; - break; + if (!obj->irelative) + return (0); + obj->irelative = false; + rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize); + for (rel = obj->pltrel; rel < rellim; rel++) { + if (ELF_R_TYPE(rel->r_info) == R_386_RELATIVE) + reloc_iresolve_one(obj, rel, lockstate); } - } - obj->irelative = false; - return (0); + return (0); +} + +int +reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate) +{ + const Elf_Rel *rellim; + const Elf_Rel *rel; + + if (!obj->irelative_nonplt) + return (0); + obj->irelative_nonplt = false; + rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize); + for (rel = obj->rel; rel < rellim; rel++) { + if (ELF_R_TYPE(rel->r_info) == R_386_IRELATIVE) + reloc_iresolve_one(obj, rel, lockstate); + } + return (0); } int diff --git a/libexec/rtld-elf/mips/reloc.c b/libexec/rtld-elf/mips/reloc.c index 8bc3e95cb4d3..b116978114b1 100644 --- a/libexec/rtld-elf/mips/reloc.c +++ b/libexec/rtld-elf/mips/reloc.c @@ -722,6 +722,15 @@ reloc_iresolve(Obj_Entry *obj __unused, return (0); } +int +reloc_iresolve_nonplt(Obj_Entry *obj __unused, + struct Struct_RtldLockState *lockstate __unused) +{ + + /* XXX not implemented */ + return (0); +} + int reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, struct Struct_RtldLockState *lockstate __unused) diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c index f5fcc6756751..e98252833014 100644 --- a/libexec/rtld-elf/powerpc/reloc.c +++ b/libexec/rtld-elf/powerpc/reloc.c @@ -652,6 +652,13 @@ reloc_iresolve(Obj_Entry *obj, return (0); } +int +reloc_iresolve_nonplt(Obj_Entry *obj __unused, + struct Struct_RtldLockState *lockstate __unused) +{ + return (0); +} + int reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, struct Struct_RtldLockState *lockstate __unused) diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c index 4a14836752c0..e2fbb109f632 100644 --- a/libexec/rtld-elf/powerpc64/reloc.c +++ b/libexec/rtld-elf/powerpc64/reloc.c @@ -652,6 +652,13 @@ reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, #endif } +int +reloc_iresolve_nonplt(Obj_Entry *obj __unused, + struct Struct_RtldLockState *lockstate __unused) +{ + return (0); +} + void init_pltgot(Obj_Entry *obj) { diff --git a/libexec/rtld-elf/riscv/reloc.c b/libexec/rtld-elf/riscv/reloc.c index c421270167f5..79a045ff0253 100644 --- a/libexec/rtld-elf/riscv/reloc.c +++ b/libexec/rtld-elf/riscv/reloc.c @@ -211,6 +211,15 @@ reloc_iresolve(Obj_Entry *obj __unused, return (0); } +int +reloc_iresolve_nonplt(Obj_Entry *obj __unused, + struct Struct_RtldLockState *lockstate __unused) +{ + + /* XXX not implemented */ + return (0); +} + int reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, struct Struct_RtldLockState *lockstate __unused) diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index ba08785762f5..b2c2f1f28765 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -3034,10 +3034,13 @@ resolve_object_ifunc(Obj_Entry *obj, bool bind_now, int flags, if (obj->ifuncs_resolved) return (0); obj->ifuncs_resolved = true; - if (!obj->irelative && !((obj->bind_now || bind_now) && obj->gnu_ifunc)) + if (!obj->irelative && !obj->irelative_nonplt && + !((obj->bind_now || bind_now) && obj->gnu_ifunc)) return (0); if (obj_disable_relro(obj) == -1 || (obj->irelative && reloc_iresolve(obj, lockstate) == -1) || + (obj->irelative_nonplt && reloc_iresolve_nonplt(obj, + lockstate) == -1) || ((obj->bind_now || bind_now) && obj->gnu_ifunc && reloc_gnu_ifunc(obj, flags, lockstate) == -1) || obj_enforce_relro(obj) == -1) diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index f21b1d79cf20..85755667fda8 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -264,6 +264,7 @@ typedef struct Struct_Obj_Entry { bool dag_inited : 1; /* Object has its DAG initialized. */ bool filtees_loaded : 1; /* Filtees loaded */ bool irelative : 1; /* Object has R_MACHDEP_IRELATIVE relocs */ + bool irelative_nonplt : 1; /* Object has R_MACHDEP_IRELATIVE non-plt relocs */ bool gnu_ifunc : 1; /* Object has references to STT_GNU_IFUNC */ bool non_plt_gnu_ifunc : 1; /* Object has non-plt IFUNC references */ bool ifuncs_resolved : 1; /* Object ifuncs were already resolved */ @@ -406,6 +407,7 @@ int reloc_non_plt(Obj_Entry *, Obj_Entry *, int flags, int reloc_plt(Obj_Entry *, int flags, struct Struct_RtldLockState *); int reloc_jmpslots(Obj_Entry *, int flags, struct Struct_RtldLockState *); int reloc_iresolve(Obj_Entry *, struct Struct_RtldLockState *); +int reloc_iresolve_nonplt(Obj_Entry *, struct Struct_RtldLockState *); int reloc_gnu_ifunc(Obj_Entry *, int flags, struct Struct_RtldLockState *); void ifunc_init(Elf_Auxinfo[__min_size(AT_COUNT)]); void pre_init(void); diff --git a/libexec/rtld-elf/sparc64/reloc.c b/libexec/rtld-elf/sparc64/reloc.c index 4b0eb7d75b19..3434ed09d82f 100644 --- a/libexec/rtld-elf/sparc64/reloc.c +++ b/libexec/rtld-elf/sparc64/reloc.c @@ -569,6 +569,15 @@ reloc_iresolve(Obj_Entry *obj __unused, return (0); } +int +reloc_iresolve_nonplt(Obj_Entry *obj __unused, + struct Struct_RtldLockState *lockstate __unused) +{ + + /* XXX not implemented */ + return (0); +} + int reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, struct Struct_RtldLockState *lockstate __unused) From 1f4fa9156db1d76537b3107c0fe2cbcc5b9de749 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 14 Feb 2020 00:12:59 +0000 Subject: [PATCH 30/39] xpt_release_simq_timeout is unused. Remove it. --- sys/cam/cam_xpt.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 6ab6e94e8e38..848692d0e229 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -248,7 +248,6 @@ static void xpt_run_allocq(struct cam_periph *periph, int sleep); static void xpt_run_allocq_task(void *context, int pending); static void xpt_run_devq(struct cam_devq *devq); static callout_func_t xpt_release_devq_timeout; -static void xpt_release_simq_timeout(void *arg) __unused; static void xpt_acquire_bus(struct cam_eb *bus); static void xpt_release_bus(struct cam_eb *bus); static uint32_t xpt_freeze_devq_device(struct cam_ed *dev, u_int count); @@ -4621,18 +4620,6 @@ xpt_release_simq(struct cam_sim *sim, int run_queue) mtx_unlock(&devq->send_mtx); } -/* - * XXX Appears to be unused. - */ -static void -xpt_release_simq_timeout(void *arg) -{ - struct cam_sim *sim; - - sim = (struct cam_sim *)arg; - xpt_release_simq(sim, /* run_queue */ TRUE); -} - void xpt_done(union ccb *done_ccb) { From 2100c6d00fcaa7219bc5806863154af5db0653ae Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 14 Feb 2020 00:13:23 +0000 Subject: [PATCH 31/39] Add a KASSERT that there's no outstanding CCBs when we call camperiphfree. We know that if there are any outstanding CCBs, then when they dereference the path that's freed at the bottom of camperiphfree there will be some flavor of panic. This moves that eventual panic to a traceback of when we free the last reference on the device, which is earlier but may not be early enough. --- sys/cam/cam_periph.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 7d8f671eecd3..f4855b819301 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include /* For KASSERTs only */ #include #include @@ -681,6 +682,10 @@ camperiphfree(struct cam_periph *periph) cam_periph_assert(periph, MA_OWNED); KASSERT(periph->periph_allocating == 0, ("%s%d: freed while allocating", periph->periph_name, periph->unit_number)); + KASSERT(periph->path->device->ccbq.dev_active == 0, + ("%s%d: freed with %d active CCBs\n", + periph->periph_name, periph->unit_number, + periph->path->device->ccbq.dev_active)); for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0) break; From 144d6690b5d9185a6665d9df83e7ffef48a09d96 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Fri, 14 Feb 2020 00:29:21 +0000 Subject: [PATCH 32/39] Exclude modifier keys from keyboard repeat logic. This restores USB keyboard driver behaviour prior to r357861. Requested by: jkim@ MFC after: 1 week Sponsored by: Mellanox Technologies --- sys/dev/usb/input/ukbd.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index c229a52d59d0..ea872c389759 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -347,6 +347,13 @@ ukbd_any_key_valid(struct ukbd_softc *sc) return (ret); } +static bool +ukbd_is_modifier_key(uint32_t key) +{ + + return (key >= 0xe0 && key <= 0xe7); +} + static void ukbd_start_timer(struct ukbd_softc *sc) { @@ -488,12 +495,9 @@ ukbd_interrupt(struct ukbd_softc *sc) { const uint32_t now = sc->sc_time_ms; unsigned key; - bool old_keys; UKBD_LOCK_ASSERT(); - old_keys = ukbd_any_key_pressed(sc); - /* Check for key changes */ for (key = 0; key != UKBD_NKEYCODE; key++) { const uint64_t mask = 1ULL << (key % 64); @@ -514,6 +518,19 @@ ukbd_interrupt(struct ukbd_softc *sc) } else { ukbd_put_key(sc, key | KEY_PRESS); + if (ukbd_is_modifier_key(key)) + continue; + + /* + * Check for first new key and set + * initial delay and [re]start timer: + */ + if (sc->sc_repeat_key == 0) { + sc->sc_co_basetime = sbinuptime(); + sc->sc_delay = sc->sc_kbd.kb_delay1; + ukbd_start_timer(sc); + } + /* set repeat time for last key */ sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; sc->sc_repeat_key = key; @@ -535,13 +552,6 @@ ukbd_interrupt(struct ukbd_softc *sc) } } - /* check for first new key and set initial delay and [re]start timer */ - if (old_keys == false && ukbd_any_key_pressed(sc) == true) { - sc->sc_co_basetime = sbinuptime(); - sc->sc_delay = sc->sc_kbd.kb_delay1; - ukbd_start_timer(sc); - } - /* wakeup keyboard system */ ukbd_event_keyinput(sc); } From 0f5f49eff7c520a94a12b2af6d8ab2212334c0b4 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Fri, 14 Feb 2020 02:22:08 +0000 Subject: [PATCH 33/39] u_char -> vm_prot_t in a couple of places, NFC The latter is a typedef of the former; the typedef exists and these bits are representing vmprot values, so use the correct type. Submitted by: sigsys@gmail.com MFC after: 3 days --- sys/kern/kern_descrip.c | 2 +- sys/kern/sys_capability.c | 4 ++-- sys/sys/capsicum.h | 2 +- sys/sys/file.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index e8d2ee296a8f..2b21e51bb688 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2898,7 +2898,7 @@ fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp) } int -fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, u_char *maxprotp, +fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, vm_prot_t *maxprotp, struct file **fpp) { int error; diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c index 8ad0eabd4278..d6a09ddcfac1 100644 --- a/sys/kern/sys_capability.c +++ b/sys/kern/sys_capability.c @@ -193,10 +193,10 @@ cap_check_failed_notcapable(const cap_rights_t *havep, const cap_rights_t *needp /* * Convert capability rights into VM access flags. */ -u_char +vm_prot_t cap_rights_to_vmprot(const cap_rights_t *havep) { - u_char maxprot; + vm_prot_t maxprot; maxprot = VM_PROT_NONE; if (cap_rights_is_set(havep, CAP_MMAP_R)) diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h index fd5743ec2fe7..8bc5195bdfe4 100644 --- a/sys/sys/capsicum.h +++ b/sys/sys/capsicum.h @@ -514,7 +514,7 @@ int cap_check(const cap_rights_t *havep, const cap_rights_t *needp); /* * Convert capability rights into VM access flags. */ -u_char cap_rights_to_vmprot(const cap_rights_t *havep); +vm_prot_t cap_rights_to_vmprot(const cap_rights_t *havep); /* * For the purposes of procstat(1) and similar tools, allow kern_descrip.c to diff --git a/sys/sys/file.h b/sys/sys/file.h index 6d6d2754e097..3cf0deefd5ba 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -247,7 +247,7 @@ extern int maxfilesperproc; /* per process limit on number of open files */ int fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); int fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, - u_char *maxprotp, struct file **fpp); + vm_prot_t *maxprotp, struct file **fpp); int fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); int fget_write(struct thread *td, int fd, cap_rights_t *rightsp, From d8b7b73571f6733583507e7eaae427c5de298317 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Fri, 14 Feb 2020 04:16:22 +0000 Subject: [PATCH 34/39] ncurses: correct check for gcc >= 5.0 The hack in question is intended to workaround seemingly bogus #line markers in cpp output. As far as I can tell, llvm cpp doesn't do this by default, so there's no reason to add -P. In our /bin/sh, the main incantation should be placed in a sub-shell in order to properly pipe the output to fgrep. The main motivation for this change is admittedly to stop emitting the noise about clang not being gcc in make -s buildworld MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D22952 --- contrib/ncurses/ncurses/base/MKlib_gen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/ncurses/ncurses/base/MKlib_gen.sh b/contrib/ncurses/ncurses/base/MKlib_gen.sh index 4f7f19de362e..83c84282c45f 100755 --- a/contrib/ncurses/ncurses/base/MKlib_gen.sh +++ b/contrib/ncurses/ncurses/base/MKlib_gen.sh @@ -73,7 +73,7 @@ USE="$3" # determine if we are using gcc, and if so, what version because the proposed # solution uses a nonstandard option. PRG=`echo "$1" | $AWK '{ sub(/^[[:space:]]*/,""); sub(/[[:space:]].*$/, ""); print; }' || exit 0` -FSF=`"$PRG" --version 2>/dev/null || exit 0 | fgrep "Free Software Foundation" | head -n 1` +FSF=`("$PRG" --version 2>/dev/null || exit 0) | fgrep "Free Software Foundation" | head -n 1` ALL=`"$PRG" -dumpversion 2>/dev/null || exit 0` ONE=`echo "$ALL" | sed -e 's/\..*$//'` if test -n "$FSF" && test -n "$ALL" && test -n "$ONE" ; then From c27ac74f9cfea08a96087135183ad70a372f735d Mon Sep 17 00:00:00 2001 From: Li-Wen Hsu Date: Fri, 14 Feb 2020 09:25:29 +0000 Subject: [PATCH 35/39] Properly fix GCC build in r357867 Submitted by: kib Sponsored by: The FreeBSD Foundation --- tests/sys/net/randsleep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sys/net/randsleep.c b/tests/sys/net/randsleep.c index 8bbad5b7557d..dfff24e90db5 100644 --- a/tests/sys/net/randsleep.c +++ b/tests/sys/net/randsleep.c @@ -37,7 +37,7 @@ #include #include -#define RANDOM_MAX (((long)1<<31) - 1) +#define RANDOM_MAX ((1U<<31) - 1) int main(int argc, char** argv){ useconds_t max_usecs, usecs; From 2207447bf4c3fa03e9dbde829712e0f31e447ba2 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Fri, 14 Feb 2020 09:36:35 +0000 Subject: [PATCH 36/39] Add basic IPDIVERT tests. Reviewed by: lwhsu,kp Differential Revision: https://reviews.freebsd.org/D23316 --- tests/sys/common/Makefile | 3 + tests/sys/common/divert.py | 83 ++++++++++++++++++++ tests/sys/netinet/Makefile | 2 +- tests/sys/netinet/divert.sh | 148 +++++++++++++++++++++++++++++++++++ tests/sys/netinet6/Makefile | 3 +- tests/sys/netinet6/divert.sh | 103 ++++++++++++++++++++++++ 6 files changed, 340 insertions(+), 2 deletions(-) create mode 100755 tests/sys/common/divert.py create mode 100755 tests/sys/netinet/divert.sh create mode 100755 tests/sys/netinet6/divert.sh diff --git a/tests/sys/common/Makefile b/tests/sys/common/Makefile index 6b656e82d696..54698e913d20 100644 --- a/tests/sys/common/Makefile +++ b/tests/sys/common/Makefile @@ -3,5 +3,8 @@ PACKAGE= tests TESTSDIR= ${TESTSBASE}/sys/common ${PACKAGE}FILES+= vnet.subr +${PACKAGE}FILES+= divert.py + +${PACKAGE}FILESMODE_divert.py=0555 .include diff --git a/tests/sys/common/divert.py b/tests/sys/common/divert.py new file mode 100755 index 000000000000..1861f87402ad --- /dev/null +++ b/tests/sys/common/divert.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# - +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Alexander V. Chernikov +# +# 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$ +# + + +import socket +import scapy.all as sc +import argparse + + +IPPROTO_DIVERT = 258 + + +def parse_args(): + parser = argparse.ArgumentParser(description='divert socket tester') + parser.add_argument('--dip', type=str, help='destination packet IP') + parser.add_argument('--divert_port', type=int, default=6668, + help='divert port to use') + parser.add_argument('--test_name', type=str, required=True, + help='test name to run') + return parser.parse_args() + + +def ipdivert_ip_output_remote_success(args): + packet = sc.IP(dst=args.dip) / sc.ICMP(type='echo-request') + with socket.socket(socket.AF_INET, socket.SOCK_RAW, IPPROTO_DIVERT) as s: + s.bind(('0.0.0.0', args.divert_port)) + s.sendto(bytes(packet), ('0.0.0.0', 0)) + + +def ipdivert_ip6_output_remote_success(args): + packet = sc.IPv6(dst=args.dip) / sc.ICMPv6EchoRequest() + with socket.socket(socket.AF_INET, socket.SOCK_RAW, IPPROTO_DIVERT) as s: + s.bind(('0.0.0.0', args.divert_port)) + s.sendto(bytes(packet), ('0.0.0.0', 0)) + + +def ipdivert_ip_input_local_success(args): + """Sends IPv4 packet to OS stack as inbound local packet.""" + packet = sc.IP(dst=args.dip) / sc.ICMP(type='echo-request') + with socket.socket(socket.AF_INET, socket.SOCK_RAW, IPPROTO_DIVERT) as s: + s.bind(('0.0.0.0', args.divert_port)) + s.sendto(bytes(packet), (args.dip, 0)) + + +# XXX: IPv6 local divert is currently not supported +# TODO: add IPv4 ifname output verification + + +def main(): + args = parse_args() + test_ptr = globals()[args.test_name] + test_ptr(args) + + +if __name__ == '__main__': + main() diff --git a/tests/sys/netinet/Makefile b/tests/sys/netinet/Makefile index 41d7d8abc7da..6d113e82ddc1 100644 --- a/tests/sys/netinet/Makefile +++ b/tests/sys/netinet/Makefile @@ -9,7 +9,7 @@ ATF_TESTS_C= ip_reass_test \ so_reuseport_lb_test \ socket_afinet -ATF_TESTS_SH= fibs_test redirect +ATF_TESTS_SH= fibs_test redirect divert PROGS= udp_dontroute tcp_user_cookie diff --git a/tests/sys/netinet/divert.sh b/tests/sys/netinet/divert.sh new file mode 100755 index 000000000000..e0688428f164 --- /dev/null +++ b/tests/sys/netinet/divert.sh @@ -0,0 +1,148 @@ +#!/usr/bin/env atf-sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Alexander V. Chernikov +# +# 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$ +# + +. $(atf_get_srcdir)/../common/vnet.subr + +load_divert_module() { + kldstat -q -n ipdivert + if [ $? -ne 0 ]; then + atf_skip "ipdivert module is not loaded" + fi +} + +atf_test_case "ipdivert_ip_output_remote_success" "cleanup" +ipdivert_ip_output_remote_success_head() { + + atf_set descr 'Test diverting IPv4 packet to remote destination' + atf_set require.user root + atf_set require.progs scapy +} + +ipdivert_ip_output_remote_success_body() { + + ids=65530 + id=`printf "%x" ${ids}` + if [ $$ -gt 65535 ]; then + xl=`printf "%x" $(($$ - 65535))` + yl="1" + else + xl=`printf "%x" $$` + yl="" + fi + + vnet_init + load_divert_module + + ip4a="192.0.2.5" + ip4b="192.0.2.6" + + script_name="../common/divert.py" + + epair=$(vnet_mkepair) + ifconfig ${epair}a up + ifconfig ${epair}a inet ${ip4a}/30 + + jname="v4t-${id}-${yl}-${xl}" + vnet_mkjail ${jname} ${epair}b + jexec ${jname} ifconfig ${epair}b up + jexec ${jname} ifconfig ${epair}b inet ${ip4b}/30 + + atf_check -s exit:0 $(atf_get_srcdir)/${script_name} \ + --dip ${ip4b} --test_name ipdivert_ip_output_remote_success + + count=`jexec ${jname} netstat -s -p icmp | grep 'Input histogram:' -A8 | grep -c 'echo: '` + # Verify redirect got installed + atf_check_equal "1" "${count}" +} + +ipdivert_ip_output_remote_success_cleanup() { + + vnet_cleanup +} + +atf_test_case "ipdivert_ip_input_local_success" "cleanup" +ipdivert_ip_input_local_success_head() { + + atf_set descr 'Test diverting IPv4 packet to remote destination' + atf_set require.user root + atf_set require.progs scapy +} + +ipdivert_ip_input_local_success_body() { + + ids=65529 + id=`printf "%x" ${ids}` + if [ $$ -gt 65535 ]; then + xl=`printf "%x" $(($$ - 65535))` + yl="1" + else + xl=`printf "%x" $$` + yl="" + fi + + vnet_init + load_divert_module + + ip4a="192.0.2.5" + ip4b="192.0.2.6" + + script_name="../common/divert.py" + + epair=$(vnet_mkepair) + ifconfig ${epair}a up + ifconfig ${epair}a inet ${ip4a}/30 + + jname="v4t-${id}-${yl}-${xl}" + vnet_mkjail ${jname} ${epair}b + jexec ${jname} ifconfig ${epair}b up + jexec ${jname} ifconfig ${epair}b inet ${ip4b}/30 + + atf_check -s exit:0 jexec ${jname} $(atf_get_srcdir)/${script_name} \ + --dip ${ip4b} --test_name ipdivert_ip_input_local_success + + count=`jexec ${jname} netstat -s -p icmp | grep 'Input histogram:' -A8 | grep -c 'echo: '` + # Verify redirect got installed + atf_check_equal "1" "${count}" +} + +ipdivert_ip_input_local_success_cleanup() { + + vnet_cleanup +} + +atf_init_test_cases() +{ + + atf_add_test_case "ipdivert_ip_output_remote_success" + atf_add_test_case "ipdivert_ip_input_local_success" +} + +# end + diff --git a/tests/sys/netinet6/Makefile b/tests/sys/netinet6/Makefile index f52c71db87ae..51f5b92c4f54 100644 --- a/tests/sys/netinet6/Makefile +++ b/tests/sys/netinet6/Makefile @@ -9,7 +9,8 @@ ATF_TESTS_SH= \ exthdr \ mld \ scapyi386 \ - redirect + redirect \ + divert ${PACKAGE}FILES+= exthdr.py ${PACKAGE}FILES+= mld.py diff --git a/tests/sys/netinet6/divert.sh b/tests/sys/netinet6/divert.sh new file mode 100755 index 000000000000..2586cdbba936 --- /dev/null +++ b/tests/sys/netinet6/divert.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env atf-sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Alexander V. Chernikov +# +# 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$ +# + +. $(atf_get_srcdir)/../common/vnet.subr + +load_divert_module() { + kldstat -q -n ipdivert + if [ $? -ne 0 ]; then + atf_skip "ipdivert module is not loaded" + fi +} + +atf_test_case "ipdivert_ip6_output_remote_success" "cleanup" +ipdivert_ip6_output_remote_success_head() { + + atf_set descr 'Test valid IPv6 redirect' + atf_set require.user root + atf_set require.progs scapy +} + +ipdivert_ip6_output_remote_success_body() { + + ids=65530 + id=`printf "%x" ${ids}` + if [ $$ -gt 65535 ]; then + xl=`printf "%x" $(($$ - 65535))` + yl="1" + else + xl=`printf "%x" $$` + yl="" + fi + + vnet_init + load_divert_module + + ip6a="2001:db8:6666:0000:${yl}:${id}:1:${xl}" + ip6b="2001:db8:6666:0000:${yl}:${id}:2:${xl}" + + script_name="../common/divert.py" + + epair=$(vnet_mkepair) + ifconfig ${epair}a up + ifconfig ${epair}a inet6 ${ip6a}/64 + + jname="v6t-${id}-${yl}-${xl}" + vnet_mkjail ${jname} ${epair}b + jexec ${jname} ifconfig ${epair}b up + jexec ${jname} ifconfig ${epair}b inet6 ${ip6b}/64 + + # wait for DAD to complete + sleep 2 + + # echo "LOCAL: ${local_ll_ip} ${local_ll_mac}" + # echo "REMOTE: ${remote_rtr_ll_ip} ${remote_rtr_mac}" + + atf_check -s exit:0 $(atf_get_srcdir)/${script_name} \ + --dip ${ip6b} --test_name ipdivert_ip6_output_remote_success + + count=`jexec ${jname} netstat -s -p icmp6 | grep 'Input histogram:' -A1 | grep -c 'echo:'` + # Verify redirect got installed + atf_check_equal "1" "${count}" +} + +ipdivert_ip6_output_remote_success_cleanup() { + + vnet_cleanup +} + +atf_init_test_cases() +{ + + atf_add_test_case "ipdivert_ip6_output_remote_success" +} + +# end + From 943c4932f34e31f9a0e4d0c31812ee551ac28da8 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 14 Feb 2020 11:20:25 +0000 Subject: [PATCH 37/39] lockmgr: retire the unused lockmgr_unlock_fast_path routine --- sys/kern/kern_lock.c | 40 ---------------------------------------- sys/sys/lockmgr.h | 2 -- 2 files changed, 42 deletions(-) diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index b48bc608e177..61977d707d17 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -1114,46 +1114,6 @@ lockmgr_xunlock_hard(struct lock *lk, uintptr_t x, u_int flags, struct lock_obje return (0); } -int -lockmgr_unlock_fast_path(struct lock *lk, u_int flags, struct lock_object *ilk) -{ - struct lock_class *class; - uintptr_t x, tid; - const char *file; - int line; - - if (KERNEL_PANICKED()) - return (0); - - file = __FILE__; - line = __LINE__; - - _lockmgr_assert(lk, KA_LOCKED, file, line); - x = lk->lk_lock; - if (__predict_true(x & LK_SHARE) != 0) { - lockmgr_note_shared_release(lk, file, line); - if (lockmgr_sunlock_try(lk, &x)) { - LOCKSTAT_PROFILE_RELEASE_RWLOCK(lockmgr__release, lk, LOCKSTAT_READER); - } else { - return (lockmgr_sunlock_hard(lk, x, flags, ilk, file, line)); - } - } else { - tid = (uintptr_t)curthread; - lockmgr_note_exclusive_release(lk, file, line); - if (!lockmgr_recursed(lk) && - atomic_cmpset_rel_ptr(&lk->lk_lock, tid, LK_UNLOCKED)) { - LOCKSTAT_PROFILE_RELEASE_RWLOCK(lockmgr__release, lk, LOCKSTAT_WRITER); - } else { - return (lockmgr_xunlock_hard(lk, x, flags, ilk, file, line)); - } - } - if (__predict_false(flags & LK_INTERLOCK)) { - class = LOCK_CLASS(ilk); - class->lc_unlock(ilk); - } - return (0); -} - /* * Lightweight entry points for common operations. * diff --git a/sys/sys/lockmgr.h b/sys/sys/lockmgr.h index 803e749e176c..fd0004618e93 100644 --- a/sys/sys/lockmgr.h +++ b/sys/sys/lockmgr.h @@ -72,8 +72,6 @@ int __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, const char *wmesg, int prio, int timo, const char *file, int line); int lockmgr_lock_fast_path(struct lock *lk, u_int flags, struct lock_object *ilk, const char *file, int line); -int lockmgr_unlock_fast_path(struct lock *lk, u_int flags, - struct lock_object *ilk); int lockmgr_slock(struct lock *lk, u_int flags, const char *file, int line); int lockmgr_xlock(struct lock *lk, u_int flags, const char *file, int line); int lockmgr_unlock(struct lock *lk); From c1b57fa7d3748e0e43ca0c986b0529b29534388c Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 14 Feb 2020 11:21:28 +0000 Subject: [PATCH 38/39] lockmgr: rename lock_fast_path to lock_flags The routine is not much of a fast path and the flags name better describes its purpose. --- sys/kern/kern_lock.c | 4 ++-- sys/kern/vfs_default.c | 2 +- sys/sys/lockmgr.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index 61977d707d17..09e56cc08005 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -934,7 +934,7 @@ lockmgr_upgrade(struct lock *lk, u_int flags, struct lock_object *ilk, } int -lockmgr_lock_fast_path(struct lock *lk, u_int flags, struct lock_object *ilk, +lockmgr_lock_flags(struct lock *lk, u_int flags, struct lock_object *ilk, const char *file, int line) { struct lock_class *class; @@ -1123,7 +1123,7 @@ lockmgr_xunlock_hard(struct lock *lk, uintptr_t x, u_int flags, struct lock_obje * 2. returning with an error after sleep * 3. unlocking the interlock * - * If in doubt, use lockmgr_*_fast_path. + * If in doubt, use lockmgr_lock_flags. */ int lockmgr_slock(struct lock *lk, u_int flags, const char *file, int line) diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 73106f4de033..013fd67fde64 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -513,7 +513,7 @@ vop_stdlock(ap) struct mtx *ilk; ilk = VI_MTX(vp); - return (lockmgr_lock_fast_path(vp->v_vnlock, ap->a_flags, + return (lockmgr_lock_flags(vp->v_vnlock, ap->a_flags, &ilk->lock_object, ap->a_file, ap->a_line)); } diff --git a/sys/sys/lockmgr.h b/sys/sys/lockmgr.h index fd0004618e93..8e5e4d43255f 100644 --- a/sys/sys/lockmgr.h +++ b/sys/sys/lockmgr.h @@ -70,7 +70,7 @@ struct thread; */ int __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, const char *wmesg, int prio, int timo, const char *file, int line); -int lockmgr_lock_fast_path(struct lock *lk, u_int flags, +int lockmgr_lock_flags(struct lock *lk, u_int flags, struct lock_object *ilk, const char *file, int line); int lockmgr_slock(struct lock *lk, u_int flags, const char *file, int line); int lockmgr_xlock(struct lock *lk, u_int flags, const char *file, int line); From 6ed30ea4c0fcb366adedaee7f3c55620cd095c68 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 14 Feb 2020 11:22:12 +0000 Subject: [PATCH 39/39] fd: annotate finstall with prediction branches --- sys/kern/kern_descrip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 2b21e51bb688..9d98275785fc 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1978,7 +1978,8 @@ finstall(struct thread *td, struct file *fp, int *fd, int flags, if (!fhold(fp)) return (EBADF); FILEDESC_XLOCK(fdp); - if ((error = fdalloc(td, 0, fd))) { + error = fdalloc(td, 0, fd); + if (__predict_false(error != 0)) { FILEDESC_XUNLOCK(fdp); fdrop(fp, td); return (error);