kernel-fxtec-pro1x/kernel/debug/kdb/kdb_main.c
Greg Kroah-Hartman 1fca2c99f4 This is the 4.19.99 stable release
-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAl4u6tsACgkQONu9yGCS
 aT693A//TExeDRnNnf+2v4TJorylyRr17BMxk/Ie2L5E6d2n/RWodsrOThAPU9tx
 5alNUkXCT8Jd31BUVnUoPoAQ4zSymSVi++XEf05wDeO0tQ982IESGaLmu9EC1uMF
 nnM5y4IdRYmFI1Zji4h5vRJckoYUlB6Mdg4BgMr4Q1KX7RkZYfe6bjs7DwM/uyMx
 jVXdFaQBD1H6F5W6A+GmgUZ36g9uNqzcBxxWwv5URj+q816NdI4bsxIJMF0v0WC+
 S54fmpS07QWIYKKsQBUepeSgEF4ECESOE2VoF1ICcnfakdPnDBmNgyPJPSrLmVf+
 itRUxoH1MewaOvoJrv+xsGBPmM29LcKH2oBmj5DR2Xstp7ACPs+OtXJEU9dUTDN4
 NhaSts5fIp0f4Y5mMn508pDUwYDAWDt99ZJWdx6aK/TRyUsHBgpxBQDt37BE3U5W
 PCBnObNe2b2KDAsVXLjX5iDYoA0+usFreveMo8uEP+ohfh0ANvJlRkzedYw7NquI
 ZCcT+I1P9q8aa0528tR332VLrQeYg+kG6LVi2kAabmRA/VtEsT0w90MY/eo2vuTU
 WlPmbs2yerv2HTm050e6MOgBZfPh7wP/FpbjsSXufj7EDywlfxF+1hXdwfrpPJeN
 fN3g0kepeUp7+kLzO40FLam/z5ndjAUhyN2SBaPzGsXjMkZdETk=
 =zvlh
 -----END PGP SIGNATURE-----

Merge 4.19.99 into android-4.19

Changes in 4.19.99
	Revert "efi: Fix debugobjects warning on 'efi_rts_work'"
	xfs: Sanity check flags of Q_XQUOTARM call
	i2c: stm32f7: rework slave_id allocation
	i2c: i2c-stm32f7: fix 10-bits check in slave free id search loop
	mfd: intel-lpss: Add default I2C device properties for Gemini Lake
	SUNRPC: Fix svcauth_gss_proxy_init()
	powerpc/pseries: Enable support for ibm,drc-info property
	powerpc/archrandom: fix arch_get_random_seed_int()
	tipc: update mon's self addr when node addr generated
	tipc: fix wrong timeout input for tipc_wait_for_cond()
	mt7601u: fix bbp version check in mt7601u_wait_bbp_ready
	crypto: sun4i-ss - fix big endian issues
	perf map: No need to adjust the long name of modules
	soc: aspeed: Fix snoop_file_poll()'s return type
	watchdog: sprd: Fix the incorrect pointer getting from driver data
	ipmi: Fix memory leak in __ipmi_bmc_register
	drm/sti: do not remove the drm_bridge that was never added
	ARM: dts: at91: nattis: set the PRLUD and HIPOW signals low
	ARM: dts: at91: nattis: make the SD-card slot work
	ixgbe: don't clear IPsec sa counters on HW clearing
	drm/virtio: fix bounds check in virtio_gpu_cmd_get_capset()
	iio: fix position relative kernel version
	apparmor: Fix network performance issue in aa_label_sk_perm
	ALSA: hda: fix unused variable warning
	apparmor: don't try to replace stale label in ptrace access check
	ARM: qcom_defconfig: Enable MAILBOX
	firmware: coreboot: Let OF core populate platform device
	PCI: iproc: Remove PAXC slot check to allow VF support
	bridge: br_arp_nd_proxy: set icmp6_router if neigh has NTF_ROUTER
	drm/hisilicon: hibmc: Don't overwrite fb helper surface depth
	signal/ia64: Use the generic force_sigsegv in setup_frame
	signal/ia64: Use the force_sig(SIGSEGV,...) in ia64_rt_sigreturn
	ASoC: wm9712: fix unused variable warning
	mailbox: mediatek: Add check for possible failure of kzalloc
	IB/rxe: replace kvfree with vfree
	IB/hfi1: Add mtu check for operational data VLs
	genirq/debugfs: Reinstate full OF path for domain name
	usb: dwc3: add EXTCON dependency for qcom
	usb: gadget: fsl_udc_core: check allocation return value and cleanup on failure
	cfg80211: regulatory: make initialization more robust
	mei: replace POLL* with EPOLL* for write queues.
	drm/msm: fix unsigned comparison with less than zero
	of: Fix property name in of_node_get_device_type
	ALSA: usb-audio: update quirk for B&W PX to remove microphone
	iwlwifi: nvm: get num of hw addresses from firmware
	staging: comedi: ni_mio_common: protect register write overflow
	netfilter: nft_osf: usage from output path is not valid
	pwm: lpss: Release runtime-pm reference from the driver's remove callback
	powerpc/pseries/memory-hotplug: Fix return value type of find_aa_index
	rtlwifi: rtl8821ae: replace _rtl8821ae_mrate_idx_to_arfr_id with generic version
	RDMA/bnxt_re: Add missing spin lock initialization
	netfilter: nf_flow_table: do not remove offload when other netns's interface is down
	powerpc/kgdb: add kgdb_arch_set/remove_breakpoint()
	tipc: eliminate message disordering during binding table update
	net: socionext: Add dummy PHY register read in phy_write()
	drm/sun4i: hdmi: Fix double flag assignation
	net: hns3: add error handler for hns3_nic_init_vector_data()
	mlxsw: reg: QEEC: Add minimum shaper fields
	mlxsw: spectrum: Set minimum shaper on MC TCs
	NTB: ntb_hw_idt: replace IS_ERR_OR_NULL with regular NULL checks
	ASoC: wm97xx: fix uninitialized regmap pointer problem
	ARM: dts: bcm283x: Correct mailbox register sizes
	pcrypt: use format specifier in kobject_add
	ASoC: sun8i-codec: add missing route for ADC
	pinctrl: meson-gxl: remove invalid GPIOX tsin_a pins
	bus: ti-sysc: Add mcasp optional clocks flag
	exportfs: fix 'passing zero to ERR_PTR()' warning
	drm: rcar-du: Fix the return value in case of error in 'rcar_du_crtc_set_crc_source()'
	drm: rcar-du: Fix vblank initialization
	net: always initialize pagedlen
	drm/dp_mst: Skip validating ports during destruction, just ref
	arm64: dts: meson-gx: Add hdmi_5v regulator as hdmi tx supply
	arm64: dts: renesas: r8a7795-es1: Add missing power domains to IPMMU nodes
	net: phy: Fix not to call phy_resume() if PHY is not attached
	IB/hfi1: Correctly process FECN and BECN in packets
	OPP: Fix missing debugfs supply directory for OPPs
	IB/rxe: Fix incorrect cache cleanup in error flow
	mailbox: ti-msgmgr: Off by one in ti_msgmgr_of_xlate()
	staging: bcm2835-camera: Abort probe if there is no camera
	staging: bcm2835-camera: fix module autoloading
	switchtec: Remove immediate status check after submitting MRPC command
	ipv6: add missing tx timestamping on IPPROTO_RAW
	pinctrl: sh-pfc: r8a7740: Add missing REF125CK pin to gether_gmii group
	pinctrl: sh-pfc: r8a7740: Add missing LCD0 marks to lcd0_data24_1 group
	pinctrl: sh-pfc: r8a7791: Remove bogus ctrl marks from qspi_data4_b group
	pinctrl: sh-pfc: r8a7791: Remove bogus marks from vin1_b_data18 group
	pinctrl: sh-pfc: sh73a0: Add missing TO pin to tpu4_to3 group
	pinctrl: sh-pfc: r8a7794: Remove bogus IPSR9 field
	pinctrl: sh-pfc: r8a77970: Add missing MOD_SEL0 field
	pinctrl: sh-pfc: r8a77980: Add missing MOD_SEL0 field
	pinctrl: sh-pfc: sh7734: Add missing IPSR11 field
	pinctrl: sh-pfc: r8a77995: Remove bogus SEL_PWM[0-3]_3 configurations
	pinctrl: sh-pfc: sh7269: Add missing PCIOR0 field
	pinctrl: sh-pfc: sh7734: Remove bogus IPSR10 value
	net: hns3: fix error handling int the hns3_get_vector_ring_chain
	vxlan: changelink: Fix handling of default remotes
	Input: nomadik-ske-keypad - fix a loop timeout test
	fork,memcg: fix crash in free_thread_stack on memcg charge fail
	clk: highbank: fix refcount leak in hb_clk_init()
	clk: qoriq: fix refcount leak in clockgen_init()
	clk: ti: fix refcount leak in ti_dt_clocks_register()
	clk: socfpga: fix refcount leak
	clk: samsung: exynos4: fix refcount leak in exynos4_get_xom()
	clk: imx6q: fix refcount leak in imx6q_clocks_init()
	clk: imx6sx: fix refcount leak in imx6sx_clocks_init()
	clk: imx7d: fix refcount leak in imx7d_clocks_init()
	clk: vf610: fix refcount leak in vf610_clocks_init()
	clk: armada-370: fix refcount leak in a370_clk_init()
	clk: kirkwood: fix refcount leak in kirkwood_clk_init()
	clk: armada-xp: fix refcount leak in axp_clk_init()
	clk: mv98dx3236: fix refcount leak in mv98dx3236_clk_init()
	clk: dove: fix refcount leak in dove_clk_init()
	MIPS: BCM63XX: drop unused and broken DSP platform device
	arm64: defconfig: Re-enable bcm2835-thermal driver
	remoteproc: qcom: q6v5-mss: Add missing clocks for MSM8996
	remoteproc: qcom: q6v5-mss: Add missing regulator for MSM8996
	drm: Fix error handling in drm_legacy_addctx
	ARM: dts: r8a7743: Remove generic compatible string from iic3
	drm/etnaviv: fix some off by one bugs
	drm/fb-helper: generic: Fix setup error path
	fork, memcg: fix cached_stacks case
	IB/usnic: Fix out of bounds index check in query pkey
	RDMA/ocrdma: Fix out of bounds index check in query pkey
	RDMA/qedr: Fix out of bounds index check in query pkey
	drm/shmob: Fix return value check in shmob_drm_probe
	arm64: dts: apq8016-sbc: Increase load on l11 for SDCARD
	spi: cadence: Correct initialisation of runtime PM
	RDMA/iw_cxgb4: Fix the unchecked ep dereference
	net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ9031
	memory: tegra: Don't invoke Tegra30+ specific memory timing setup on Tegra20
	drm/etnaviv: NULL vs IS_ERR() buf in etnaviv_core_dump()
	media: s5p-jpeg: Correct step and max values for V4L2_CID_JPEG_RESTART_INTERVAL
	kbuild: mark prepare0 as PHONY to fix external module build
	crypto: brcm - Fix some set-but-not-used warning
	crypto: tgr192 - fix unaligned memory access
	ASoC: imx-sgtl5000: put of nodes if finding codec fails
	IB/iser: Pass the correct number of entries for dma mapped SGL
	net: hns3: fix wrong combined count returned by ethtool -l
	media: tw9910: Unregister subdevice with v4l2-async
	IB/mlx5: Don't override existing ip_protocol
	rtc: cmos: ignore bogus century byte
	spi/topcliff_pch: Fix potential NULL dereference on allocation error
	net: hns3: fix bug of ethtool_ops.get_channels for VF
	ARM: dts: sun8i-a23-a33: Move NAND controller device node to sort by address
	clk: sunxi-ng: sun8i-a23: Enable PLL-MIPI LDOs when ungating it
	iwlwifi: mvm: avoid possible access out of array.
	net/mlx5: Take lock with IRQs disabled to avoid deadlock
	ip_tunnel: Fix route fl4 init in ip_md_tunnel_xmit
	arm64: dts: allwinner: h6: Move GIC device node fix base address ordering
	iwlwifi: mvm: fix A-MPDU reference assignment
	bus: ti-sysc: Fix timer handling with drop pm_runtime_irq_safe()
	tty: ipwireless: Fix potential NULL pointer dereference
	driver: uio: fix possible memory leak in __uio_register_device
	driver: uio: fix possible use-after-free in __uio_register_device
	crypto: crypto4xx - Fix wrong ppc4xx_trng_probe()/ppc4xx_trng_remove() arguments
	driver core: Fix DL_FLAG_AUTOREMOVE_SUPPLIER device link flag handling
	driver core: Avoid careless re-use of existing device links
	driver core: Do not resume suppliers under device_links_write_lock()
	driver core: Fix handling of runtime PM flags in device_link_add()
	driver core: Do not call rpm_put_suppliers() in pm_runtime_drop_link()
	ARM: dts: lpc32xx: add required clocks property to keypad device node
	ARM: dts: lpc32xx: reparent keypad controller to SIC1
	ARM: dts: lpc32xx: fix ARM PrimeCell LCD controller variant
	ARM: dts: lpc32xx: fix ARM PrimeCell LCD controller clocks property
	ARM: dts: lpc32xx: phy3250: fix SD card regulator voltage
	drm/xen-front: Fix mmap attributes for display buffers
	iwlwifi: mvm: fix RSS config command
	staging: most: cdev: add missing check for cdev_add failure
	clk: ingenic: jz4740: Fix gating of UDC clock
	rtc: ds1672: fix unintended sign extension
	thermal: mediatek: fix register index error
	arm64: dts: msm8916: remove bogus argument to the cpu clock
	ath10k: fix dma unmap direction for management frames
	net: phy: fixed_phy: Fix fixed_phy not checking GPIO
	rtc: ds1307: rx8130: Fix alarm handling
	net/smc: original socket family in inet_sock_diag
	rtc: 88pm860x: fix unintended sign extension
	rtc: 88pm80x: fix unintended sign extension
	rtc: pm8xxx: fix unintended sign extension
	fbdev: chipsfb: remove set but not used variable 'size'
	iw_cxgb4: use tos when importing the endpoint
	iw_cxgb4: use tos when finding ipv6 routes
	ipmi: kcs_bmc: handle devm_kasprintf() failure case
	xsk: add missing smp_rmb() in xsk_mmap
	drm/etnaviv: potential NULL dereference
	ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers
	ntb_hw_switchtec: NT req id mapping table register entry number should be 512
	pinctrl: sh-pfc: emev2: Add missing pinmux functions
	pinctrl: sh-pfc: r8a7791: Fix scifb2_data_c pin group
	pinctrl: sh-pfc: r8a7792: Fix vin1_data18_b pin group
	pinctrl: sh-pfc: sh73a0: Fix fsic_spdif pin groups
	RDMA/mlx5: Fix memory leak in case we fail to add an IB device
	driver core: Fix possible supplier PM-usage counter imbalance
	PCI: endpoint: functions: Use memcpy_fromio()/memcpy_toio()
	usb: phy: twl6030-usb: fix possible use-after-free on remove
	block: don't use bio->bi_vcnt to figure out segment number
	keys: Timestamp new keys
	net: dsa: b53: Fix default VLAN ID
	net: dsa: b53: Properly account for VLAN filtering
	net: dsa: b53: Do not program CPU port's PVID
	mt76: usb: fix possible memory leak in mt76u_buf_free
	media: sh: migor: Include missing dma-mapping header
	vfio_pci: Enable memory accesses before calling pci_map_rom
	hwmon: (pmbus/tps53679) Fix driver info initialization in probe routine
	mdio_bus: Fix PTR_ERR() usage after initialization to constant
	KVM: PPC: Release all hardware TCE tables attached to a group
	staging: r8822be: check kzalloc return or bail
	dmaengine: mv_xor: Use correct device for DMA API
	cdc-wdm: pass return value of recover_from_urb_loss
	brcmfmac: create debugfs files for bus-specific layer
	regulator: pv88060: Fix array out-of-bounds access
	regulator: pv88080: Fix array out-of-bounds access
	regulator: pv88090: Fix array out-of-bounds access
	net: dsa: qca8k: Enable delay for RGMII_ID mode
	net/mlx5: Delete unused FPGA QPN variable
	drm/nouveau/bios/ramcfg: fix missing parentheses when calculating RON
	drm/nouveau/pmu: don't print reply values if exec is false
	drm/nouveau: fix missing break in switch statement
	driver core: Fix PM-runtime for links added during consumer probe
	ASoC: qcom: Fix of-node refcount unbalance in apq8016_sbc_parse_of()
	net: dsa: fix unintended change of bridge interface STP state
	fs/nfs: Fix nfs_parse_devname to not modify it's argument
	staging: rtlwifi: Use proper enum for return in halmac_parse_psd_data_88xx
	powerpc/64s: Fix logic when handling unknown CPU features
	NFS: Fix a soft lockup in the delegation recovery code
	perf: Copy parent's address filter offsets on clone
	perf, pt, coresight: Fix address filters for vmas with non-zero offset
	clocksource/drivers/sun5i: Fail gracefully when clock rate is unavailable
	clocksource/drivers/exynos_mct: Fix error path in timer resources initialization
	platform/x86: wmi: fix potential null pointer dereference
	NFS/pnfs: Bulk destroy of layouts needs to be safe w.r.t. umount
	mmc: sdhci-brcmstb: handle mmc_of_parse() errors during probe
	iommu: Fix IOMMU debugfs fallout
	ARM: 8847/1: pm: fix HYP/SVC mode mismatch when MCPM is used
	ARM: 8848/1: virt: Align GIC version check with arm64 counterpart
	ARM: 8849/1: NOMMU: Fix encodings for PMSAv8's PRBAR4/PRLAR4
	regulator: wm831x-dcdc: Fix list of wm831x_dcdc_ilim from mA to uA
	ath10k: Fix length of wmi tlv command for protected mgmt frames
	netfilter: nft_set_hash: fix lookups with fixed size hash on big endian
	netfilter: nft_set_hash: bogus element self comparison from deactivation path
	net: sched: act_csum: Fix csum calc for tagged packets
	hwrng: bcm2835 - fix probe as platform device
	iommu/vt-d: Fix NULL pointer reference in intel_svm_bind_mm()
	NFS: Add missing encode / decode sequence_maxsz to v4.2 operations
	NFSv4/flexfiles: Fix invalid deref in FF_LAYOUT_DEVID_NODE()
	net: aquantia: fixed instack structure overflow
	powerpc/mm: Check secondary hash page table
	media: dvb/earth-pt1: fix wrong initialization for demod blocks
	rbd: clear ->xferred on error from rbd_obj_issue_copyup()
	PCI: Fix "try" semantics of bus and slot reset
	nios2: ksyms: Add missing symbol exports
	x86/mm: Remove unused variable 'cpu'
	scsi: megaraid_sas: reduce module load time
	nfp: fix simple vNIC mailbox length
	drivers/rapidio/rio_cm.c: fix potential oops in riocm_ch_listen()
	xen, cpu_hotplug: Prevent an out of bounds access
	net/mlx5: Fix multiple updates of steering rules in parallel
	net/mlx5e: IPoIB, Fix RX checksum statistics update
	net: sh_eth: fix a missing check of of_get_phy_mode
	regulator: lp87565: Fix missing register for LP87565_BUCK_0
	soc: amlogic: gx-socinfo: Add mask for each SoC packages
	media: ivtv: update *pos correctly in ivtv_read_pos()
	media: cx18: update *pos correctly in cx18_read_pos()
	media: wl128x: Fix an error code in fm_download_firmware()
	media: cx23885: check allocation return
	regulator: tps65086: Fix tps65086_ldoa1_ranges for selector 0xB
	crypto: ccree - reduce kernel stack usage with clang
	jfs: fix bogus variable self-initialization
	tipc: tipc clang warning
	m68k: mac: Fix VIA timer counter accesses
	ARM: dts: sun8i: a33: Reintroduce default pinctrl muxing
	arm64: dts: allwinner: a64: Add missing PIO clocks
	ARM: dts: sun9i: optimus: Fix fixed-regulators
	net: phy: don't clear BMCR in genphy_soft_reset
	ARM: OMAP2+: Fix potentially uninitialized return value for _setup_reset()
	net: dsa: Avoid null pointer when failing to connect to PHY
	soc: qcom: cmd-db: Fix an error code in cmd_db_dev_probe()
	media: davinci-isif: avoid uninitialized variable use
	media: tw5864: Fix possible NULL pointer dereference in tw5864_handle_frame
	spi: tegra114: clear packed bit for unpacked mode
	spi: tegra114: fix for unpacked mode transfers
	spi: tegra114: terminate dma and reset on transfer timeout
	spi: tegra114: flush fifos
	spi: tegra114: configure dma burst size to fifo trig level
	bus: ti-sysc: Fix sysc_unprepare() when no clocks have been allocated
	soc/fsl/qe: Fix an error code in qe_pin_request()
	spi: bcm2835aux: fix driver to not allow 65535 (=-1) cs-gpios
	drm/fb-helper: generic: Call drm_client_add() after setup is done
	arm64/vdso: don't leak kernel addresses
	rtc: Fix timestamp value for RTC_TIMESTAMP_BEGIN_1900
	rtc: mt6397: Don't call irq_dispose_mapping.
	ehea: Fix a copy-paste err in ehea_init_port_res
	bpf: Add missed newline in verifier verbose log
	drm/vmwgfx: Remove set but not used variable 'restart'
	scsi: qla2xxx: Unregister chrdev if module initialization fails
	of: use correct function prototype for of_overlay_fdt_apply()
	net/sched: cbs: fix port_rate miscalculation
	clk: qcom: Skip halt checks on gcc_pcie_0_pipe_clk for 8998
	ACPI: button: reinitialize button state upon resume
	firmware: arm_scmi: fix of_node leak in scmi_mailbox_check
	rxrpc: Fix detection of out of order acks
	scsi: target/core: Fix a race condition in the LUN lookup code
	brcmfmac: fix leak of mypkt on error return path
	ARM: pxa: ssp: Fix "WARNING: invalid free of devm_ allocated data"
	PCI: rockchip: Fix rockchip_pcie_ep_assert_intx() bitwise operations
	net: hns3: fix for vport->bw_limit overflow problem
	hwmon: (w83627hf) Use request_muxed_region for Super-IO accesses
	perf/core: Fix the address filtering fix
	staging: android: vsoc: fix copy_from_user overrun
	PCI: dwc: Fix dw_pcie_ep_find_capability() to return correct capability offset
	soc: amlogic: meson-gx-pwrc-vpu: Fix power on/off register bitmask
	platform/x86: alienware-wmi: fix kfree on potentially uninitialized pointer
	tipc: set sysctl_tipc_rmem and named_timeout right range
	usb: typec: tcpm: Notify the tcpc to start connection-detection for SRPs
	selftests/ipc: Fix msgque compiler warnings
	net: hns3: fix loop condition of hns3_get_tx_timeo_queue_info()
	powerpc: vdso: Make vdso32 installation conditional in vdso_install
	ARM: dts: ls1021: Fix SGMII PCS link remaining down after PHY disconnect
	media: ov2659: fix unbalanced mutex_lock/unlock
	6lowpan: Off by one handling ->nexthdr
	dmaengine: axi-dmac: Don't check the number of frames for alignment
	ALSA: usb-audio: Handle the error from snd_usb_mixer_apply_create_quirk()
	afs: Fix AFS file locking to allow fine grained locks
	afs: Further fix file locking
	NFS: Don't interrupt file writeout due to fatal errors
	coresight: catu: fix clang build warning
	s390/kexec_file: Fix potential segment overlap in ELF loader
	irqchip/gic-v3-its: fix some definitions of inner cacheability attributes
	scsi: qla2xxx: Fix a format specifier
	scsi: qla2xxx: Fix error handling in qlt_alloc_qfull_cmd()
	scsi: qla2xxx: Avoid that qlt_send_resp_ctio() corrupts memory
	KVM: PPC: Book3S HV: Fix lockdep warning when entering the guest
	netfilter: nft_flow_offload: add entry to flowtable after confirmation
	PCI: iproc: Enable iProc config read for PAXBv2
	ARM: dts: logicpd-som-lv: Fix MMC1 card detect
	packet: in recvmsg msg_name return at least sizeof sockaddr_ll
	ASoC: fix valid stream condition
	usb: gadget: fsl: fix link error against usb-gadget module
	dwc2: gadget: Fix completed transfer size calculation in DDMA
	IB/mlx5: Add missing XRC options to QP optional params mask
	RDMA/rxe: Consider skb reserve space based on netdev of GID
	iommu/vt-d: Make kernel parameter igfx_off work with vIOMMU
	net: ena: fix swapped parameters when calling ena_com_indirect_table_fill_entry
	net: ena: fix: Free napi resources when ena_up() fails
	net: ena: fix incorrect test of supported hash function
	net: ena: fix ena_com_fill_hash_function() implementation
	dmaengine: tegra210-adma: restore channel status
	watchdog: rtd119x_wdt: Fix remove function
	mmc: core: fix possible use after free of host
	lightnvm: pblk: fix lock order in pblk_rb_tear_down_check
	ath10k: Fix encoding for protected management frames
	afs: Fix the afs.cell and afs.volume xattr handlers
	vfio/mdev: Avoid release parent reference during error path
	vfio/mdev: Follow correct remove sequence
	vfio/mdev: Fix aborting mdev child device removal if one fails
	l2tp: Fix possible NULL pointer dereference
	ALSA: aica: Fix a long-time build breakage
	media: omap_vout: potential buffer overflow in vidioc_dqbuf()
	media: davinci/vpbe: array underflow in vpbe_enum_outputs()
	platform/x86: alienware-wmi: printing the wrong error code
	crypto: caam - fix caam_dump_sg that iterates through scatterlist
	netfilter: ebtables: CONFIG_COMPAT: reject trailing data after last rule
	pwm: meson: Consider 128 a valid pre-divider
	pwm: meson: Don't disable PWM when setting duty repeatedly
	ARM: riscpc: fix lack of keyboard interrupts after irq conversion
	nfp: bpf: fix static check error through tightening shift amount adjustment
	kdb: do a sanity check on the cpu in kdb_per_cpu()
	netfilter: nf_tables: correct NFT_LOGLEVEL_MAX value
	backlight: lm3630a: Return 0 on success in update_status functions
	thermal: rcar_gen3_thermal: fix interrupt type
	thermal: cpu_cooling: Actually trace CPU load in thermal_power_cpu_get_power
	EDAC/mc: Fix edac_mc_find() in case no device is found
	afs: Fix key leak in afs_release() and afs_evict_inode()
	afs: Don't invalidate callback if AFS_VNODE_DIR_VALID not set
	afs: Fix lock-wait/callback-break double locking
	afs: Fix double inc of vnode->cb_break
	ARM: dts: sun8i-h3: Fix wifi in Beelink X2 DT
	clk: meson: gxbb: no spread spectrum on mpll0
	clk: meson: axg: spread spectrum is on mpll2
	dmaengine: tegra210-adma: Fix crash during probe
	arm64: dts: meson: libretech-cc: set eMMC as removable
	RDMA/qedr: Fix incorrect device rate.
	spi: spi-fsl-spi: call spi_finalize_current_message() at the end
	crypto: ccp - fix AES CFB error exposed by new test vectors
	crypto: ccp - Fix 3DES complaint from ccp-crypto module
	serial: stm32: fix word length configuration
	serial: stm32: fix rx error handling
	serial: stm32: fix rx data length when parity enabled
	serial: stm32: fix transmit_chars when tx is stopped
	serial: stm32: Add support of TC bit status check
	serial: stm32: fix wakeup source initialization
	misc: sgi-xp: Properly initialize buf in xpc_get_rsvd_page_pa
	iommu: Add missing new line for dma type
	iommu: Use right function to get group for device
	signal/bpfilter: Fix bpfilter_kernl to use send_sig not force_sig
	signal/cifs: Fix cifs_put_tcp_session to call send_sig instead of force_sig
	inet: frags: call inet_frags_fini() after unregister_pernet_subsys()
	net: hns3: fix a memory leak issue for hclge_map_unmap_ring_to_vf_vector
	crypto: talitos - fix AEAD processing.
	netvsc: unshare skb in VF rx handler
	net: core: support XDP generic on stacked devices.
	RDMA/uverbs: check for allocation failure in uapi_add_elm()
	net: don't clear sock->sk early to avoid trouble in strparser
	phy: qcom-qusb2: fix missing assignment of ret when calling clk_prepare_enable
	cpufreq: brcmstb-avs-cpufreq: Fix initial command check
	cpufreq: brcmstb-avs-cpufreq: Fix types for voltage/frequency
	clk: sunxi-ng: sun50i-h6-r: Fix incorrect W1 clock gate register
	media: vivid: fix incorrect assignment operation when setting video mode
	crypto: inside-secure - fix zeroing of the request in ahash_exit_inv
	crypto: inside-secure - fix queued len computation
	arm64: dts: renesas: ebisu: Remove renesas, no-ether-link property
	mpls: fix warning with multi-label encap
	serial: stm32: fix a recursive locking in stm32_config_rs485
	arm64: dts: meson-gxm-khadas-vim2: fix gpio-keys-polled node
	arm64: dts: meson-gxm-khadas-vim2: fix Bluetooth support
	iommu/vt-d: Duplicate iommu_resv_region objects per device list
	phy: usb: phy-brcm-usb: Remove sysfs attributes upon driver removal
	firmware: arm_scmi: fix bitfield definitions for SENSOR_DESC attributes
	firmware: arm_scmi: update rate_discrete in clock_describe_rates_get
	ntb_hw_switchtec: potential shift wrapping bug in switchtec_ntb_init_sndev()
	ASoC: meson: axg-tdmin: right_j is not supported
	ASoC: meson: axg-tdmout: right_j is not supported
	qed: iWARP - Use READ_ONCE and smp_store_release to access ep->state
	qed: iWARP - fix uninitialized callback
	powerpc/cacheinfo: add cacheinfo_teardown, cacheinfo_rebuild
	powerpc/pseries/mobility: rebuild cacheinfo hierarchy post-migration
	bpf: fix the check that forwarding is enabled in bpf_ipv6_fib_lookup
	IB/hfi1: Handle port down properly in pio
	drm/msm/mdp5: Fix mdp5_cfg_init error return
	net: netem: fix backlog accounting for corrupted GSO frames
	net/udp_gso: Allow TX timestamp with UDP GSO
	net/af_iucv: build proper skbs for HiperTransport
	net/af_iucv: always register net_device notifier
	ASoC: ti: davinci-mcasp: Fix slot mask settings when using multiple AXRs
	rtc: pcf8563: Fix interrupt trigger method
	rtc: pcf8563: Clear event flags and disable interrupts before requesting irq
	ARM: dts: iwg20d-q7-common: Fix SDHI1 VccQ regularor
	net/sched: cbs: Fix error path of cbs_module_init
	arm64: dts: allwinner: h6: Pine H64: Add interrupt line for RTC
	drm/msm/a3xx: remove TPL1 regs from snapshot
	ip6_fib: Don't discard nodes with valid routing information in fib6_locate_1()
	perf/ioctl: Add check for the sample_period value
	dmaengine: hsu: Revert "set HSU_CH_MTSR to memory width"
	clk: qcom: Fix -Wunused-const-variable
	nvmem: imx-ocotp: Ensure WAIT bits are preserved when setting timing
	nvmem: imx-ocotp: Change TIMING calculation to u-boot algorithm
	tools: bpftool: use correct argument in cgroup errors
	backlight: pwm_bl: Fix heuristic to determine number of brightness levels
	fork,memcg: alloc_thread_stack_node needs to set tsk->stack
	bnxt_en: Fix ethtool selftest crash under error conditions.
	bnxt_en: Suppress error messages when querying DSCP DCB capabilities.
	iommu/amd: Make iommu_disable safer
	mfd: intel-lpss: Release IDA resources
	rxrpc: Fix uninitialized error code in rxrpc_send_data_packet()
	xprtrdma: Fix use-after-free in rpcrdma_post_recvs
	um: Fix IRQ controller regression on console read
	PM: ACPI/PCI: Resume all devices during hibernation
	ACPI: PM: Simplify and fix PM domain hibernation callbacks
	ACPI: PM: Introduce "poweroff" callbacks for ACPI PM domain and LPSS
	fsi/core: Fix error paths on CFAM init
	devres: allow const resource arguments
	fsi: sbefifo: Don't fail operations when in SBE IPL state
	RDMA/hns: Fixs hw access invalid dma memory error
	PCI: mobiveil: Remove the flag MSI_FLAG_MULTI_PCI_MSI
	PCI: mobiveil: Fix devfn check in mobiveil_pcie_valid_device()
	PCI: mobiveil: Fix the valid check for inbound and outbound windows
	ceph: fix "ceph.dir.rctime" vxattr value
	net: pasemi: fix an use-after-free in pasemi_mac_phy_init()
	net/tls: fix socket wmem accounting on fallback with netem
	x86/pgtable/32: Fix LOWMEM_PAGES constant
	xdp: fix possible cq entry leak
	ARM: stm32: use "depends on" instead of "if" after prompt
	scsi: libfc: fix null pointer dereference on a null lport
	xfrm interface: ifname may be wrong in logs
	drm/panel: make drm_panel.h self-contained
	clk: sunxi-ng: v3s: add the missing PLL_DDR1
	PM: sleep: Fix possible overflow in pm_system_cancel_wakeup()
	libertas_tf: Use correct channel range in lbtf_geo_init
	qed: reduce maximum stack frame size
	usb: host: xhci-hub: fix extra endianness conversion
	media: rcar-vin: Clean up correct notifier in error path
	mic: avoid statically declaring a 'struct device'.
	x86/kgbd: Use NMI_VECTOR not APIC_DM_NMI
	crypto: ccp - Reduce maximum stack usage
	ALSA: aoa: onyx: always initialize register read value
	arm64: dts: renesas: r8a77995: Fix register range of display node
	tipc: reduce risk of wakeup queue starvation
	ARM: dts: stm32: add missing vdda-supply to adc on stm32h743i-eval
	net/mlx5: Fix mlx5_ifc_query_lag_out_bits
	cifs: fix rmmod regression in cifs.ko caused by force_sig changes
	iio: tsl2772: Use devm_add_action_or_reset for tsl2772_chip_off
	net: fix bpf_xdp_adjust_head regression for generic-XDP
	spi: bcm-qspi: Fix BSPI QUAD and DUAL mode support when using flex mode
	cxgb4: smt: Add lock for atomic_dec_and_test
	crypto: caam - free resources in case caam_rng registration failed
	ext4: set error return correctly when ext4_htree_store_dirent fails
	RDMA/hns: Bugfix for slab-out-of-bounds when unloading hip08 driver
	RDMA/hns: bugfix for slab-out-of-bounds when loading hip08 driver
	ASoC: es8328: Fix copy-paste error in es8328_right_line_controls
	ASoC: cs4349: Use PM ops 'cs4349_runtime_pm'
	ASoC: wm8737: Fix copy-paste error in wm8737_snd_controls
	net/rds: Add a few missing rds_stat_names entries
	tools: bpftool: fix arguments for p_err() in do_event_pipe()
	tools: bpftool: fix format strings and arguments for jsonw_printf()
	drm: rcar-du: lvds: Fix bridge_to_rcar_lvds
	bnxt_en: Fix handling FRAG_ERR when NVM_INSTALL_UPDATE cmd fails
	signal: Allow cifs and drbd to receive their terminating signals
	powerpc/64s/radix: Fix memory hot-unplug page table split
	ASoC: sun4i-i2s: RX and TX counter registers are swapped
	dmaengine: dw: platform: Switch to acpi_dma_controller_register()
	rtc: rv3029: revert error handling patch to rv3029_eeprom_write()
	mac80211: minstrel_ht: fix per-group max throughput rate initialization
	i40e: reduce stack usage in i40e_set_fc
	media: atmel: atmel-isi: fix timeout value for stop streaming
	ARM: 8896/1: VDSO: Don't leak kernel addresses
	rtc: pcf2127: bugfix: read rtc disables watchdog
	mips: avoid explicit UB in assignment of mips_io_port_base
	media: em28xx: Fix exception handling in em28xx_alloc_urbs()
	iommu/mediatek: Fix iova_to_phys PA start for 4GB mode
	ahci: Do not export local variable ahci_em_messages
	rxrpc: Fix lack of conn cleanup when local endpoint is cleaned up [ver #2]
	Partially revert "kfifo: fix kfifo_alloc() and kfifo_init()"
	hwmon: (lm75) Fix write operations for negative temperatures
	net/sched: cbs: Set default link speed to 10 Mbps in cbs_set_port_rate
	power: supply: Init device wakeup after device_add()
	x86, perf: Fix the dependency of the x86 insn decoder selftest
	staging: greybus: light: fix a couple double frees
	irqdomain: Add the missing assignment of domain->fwnode for named fwnode
	bcma: fix incorrect update of BCMA_CORE_PCI_MDIO_DATA
	usb: typec: tps6598x: Fix build error without CONFIG_REGMAP_I2C
	bcache: Fix an error code in bch_dump_read()
	iio: dac: ad5380: fix incorrect assignment to val
	netfilter: ctnetlink: honor IPS_OFFLOAD flag
	ath9k: dynack: fix possible deadlock in ath_dynack_node_{de}init
	wcn36xx: use dynamic allocation for large variables
	tty: serial: fsl_lpuart: Use appropriate lpuart32_* I/O funcs
	ARM: dts: aspeed-g5: Fixe gpio-ranges upper limit
	xsk: avoid store-tearing when assigning queues
	xsk: avoid store-tearing when assigning umem
	led: triggers: Fix dereferencing of null pointer
	net: sonic: return NETDEV_TX_OK if failed to map buffer
	net: hns3: fix error VF index when setting VLAN offload
	rtlwifi: Fix file release memory leak
	ARM: dts: logicpd-som-lv: Fix i2c2 and i2c3 Pin mux
	f2fs: fix wrong error injection path in inc_valid_block_count()
	f2fs: fix error path of f2fs_convert_inline_page()
	scsi: fnic: fix msix interrupt allocation
	Btrfs: fix hang when loading existing inode cache off disk
	Btrfs: fix inode cache waiters hanging on failure to start caching thread
	Btrfs: fix inode cache waiters hanging on path allocation failure
	btrfs: use correct count in btrfs_file_write_iter()
	ixgbe: sync the first fragment unconditionally
	hwmon: (shtc1) fix shtc1 and shtw1 id mask
	net: sonic: replace dev_kfree_skb in sonic_send_packet
	pinctrl: iproc-gpio: Fix incorrect pinconf configurations
	gpio/aspeed: Fix incorrect number of banks
	ath10k: adjust skb length in ath10k_sdio_mbox_rx_packet
	RDMA/cma: Fix false error message
	net/rds: Fix 'ib_evt_handler_call' element in 'rds_ib_stat_names'
	um: Fix off by one error in IRQ enumeration
	bnxt_en: Increase timeout for HWRM_DBG_COREDUMP_XX commands
	f2fs: fix to avoid accessing uninitialized field of inode page in is_alive()
	mailbox: qcom-apcs: fix max_register value
	clk: actions: Fix factor clk struct member access
	powerpc/mm/mce: Keep irqs disabled during lockless page table walk
	bpf: fix BTF limits
	crypto: hisilicon - Matching the dma address for dma_pool_free()
	iommu/amd: Wait for completion of IOTLB flush in attach_device
	net: aquantia: Fix aq_vec_isr_legacy() return value
	cxgb4: Signedness bug in init_one()
	net: hisilicon: Fix signedness bug in hix5hd2_dev_probe()
	net: broadcom/bcmsysport: Fix signedness in bcm_sysport_probe()
	net: netsec: Fix signedness bug in netsec_probe()
	net: socionext: Fix a signedness bug in ave_probe()
	net: stmmac: dwmac-meson8b: Fix signedness bug in probe
	net: axienet: fix a signedness bug in probe
	of: mdio: Fix a signedness bug in of_phy_get_and_connect()
	net: nixge: Fix a signedness bug in nixge_probe()
	net: ethernet: stmmac: Fix signedness bug in ipq806x_gmac_of_parse()
	net: sched: cbs: Avoid division by zero when calculating the port rate
	nvme: retain split access workaround for capability reads
	net: stmmac: gmac4+: Not all Unicast addresses may be available
	rxrpc: Fix trace-after-put looking at the put connection record
	mac80211: accept deauth frames in IBSS mode
	llc: fix another potential sk_buff leak in llc_ui_sendmsg()
	llc: fix sk_buff refcounting in llc_conn_state_process()
	ip6erspan: remove the incorrect mtu limit for ip6erspan
	net: stmmac: fix length of PTP clock's name string
	net: stmmac: fix disabling flexible PPS output
	sctp: add chunks to sk_backlog when the newsk sk_socket is not set
	s390/qeth: Fix error handling during VNICC initialization
	s390/qeth: Fix initialization of vnicc cmd masks during set online
	act_mirred: Fix mirred_init_module error handling
	net: avoid possible false sharing in sk_leave_memory_pressure()
	net: add {READ|WRITE}_ONCE() annotations on ->rskq_accept_head
	tcp: annotate lockless access to tcp_memory_pressure
	net/smc: receive returns without data
	net/smc: receive pending data after RCV_SHUTDOWN
	drm/msm/dsi: Implement reset correctly
	vhost/test: stop device before reset
	dmaengine: imx-sdma: fix size check for sdma script_number
	firmware: dmi: Fix unlikely out-of-bounds read in save_mem_devices
	arm64: hibernate: check pgd table allocation
	net: netem: fix error path for corrupted GSO frames
	net: netem: correct the parent's backlog when corrupted packet was dropped
	xsk: Fix registration of Rx-only sockets
	bpf, offload: Unlock on error in bpf_offload_dev_create()
	afs: Fix missing timeout reset
	net: qca_spi: Move reset_count to struct qcaspi
	hv_netvsc: Fix offset usage in netvsc_send_table()
	hv_netvsc: Fix send_table offset in case of a host bug
	afs: Fix large file support
	drm: panel-lvds: Potential Oops in probe error handling
	hwrng: omap3-rom - Fix missing clock by probing with device tree
	dpaa_eth: perform DMA unmapping before read
	dpaa_eth: avoid timestamp read on error paths
	MIPS: Loongson: Fix return value of loongson_hwmon_init
	hv_netvsc: flag software created hash value
	net: neigh: use long type to store jiffies delta
	packet: fix data-race in fanout_flow_is_huge()
	i2c: stm32f7: report dma error during probe
	mmc: sdio: fix wl1251 vendor id
	mmc: core: fix wl1251 sdio quirks
	affs: fix a memory leak in affs_remount
	afs: Remove set but not used variables 'before', 'after'
	dmaengine: ti: edma: fix missed failure handling
	drm/radeon: fix bad DMA from INTERRUPT_CNTL2
	arm64: dts: juno: Fix UART frequency
	samples/bpf: Fix broken xdp_rxq_info due to map order assumptions
	usb: dwc3: Allow building USB_DWC3_QCOM without EXTCON
	IB/iser: Fix dma_nents type definition
	serial: stm32: fix clearing interrupt error flags
	arm64: dts: meson-gxm-khadas-vim2: fix uart_A bluetooth node
	m68k: Call timer_interrupt() with interrupts disabled
	Linux 4.19.99

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ieabeab79ea5c8cb4b6b1552702fa5d6100cea5db
2020-01-27 15:55:44 +01:00

2939 lines
70 KiB
C

/*
* Kernel Debugger Architecture Independent Main Code
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1999-2004 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
* Xscale (R) modifications copyright (C) 2003 Intel Corporation.
* Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved.
*/
#include <linux/ctype.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/kmsg_dump.h>
#include <linux/reboot.h>
#include <linux/sched.h>
#include <linux/sched/loadavg.h>
#include <linux/sched/stat.h>
#include <linux/sched/debug.h>
#include <linux/sysrq.h>
#include <linux/smp.h>
#include <linux/utsname.h>
#include <linux/vmalloc.h>
#include <linux/atomic.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/kallsyms.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
#include <linux/notifier.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nmi.h>
#include <linux/time.h>
#include <linux/ptrace.h>
#include <linux/sysctl.h>
#include <linux/cpu.h>
#include <linux/kdebug.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include "kdb_private.h"
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "kdb."
static int kdb_cmd_enabled = CONFIG_KDB_DEFAULT_ENABLE;
module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600);
char kdb_grep_string[KDB_GREP_STRLEN];
int kdb_grepping_flag;
EXPORT_SYMBOL(kdb_grepping_flag);
int kdb_grep_leading;
int kdb_grep_trailing;
/*
* Kernel debugger state flags
*/
int kdb_flags;
/*
* kdb_lock protects updates to kdb_initial_cpu. Used to
* single thread processors through the kernel debugger.
*/
int kdb_initial_cpu = -1; /* cpu number that owns kdb */
int kdb_nextline = 1;
int kdb_state; /* General KDB state */
struct task_struct *kdb_current_task;
EXPORT_SYMBOL(kdb_current_task);
struct pt_regs *kdb_current_regs;
const char *kdb_diemsg;
static int kdb_go_count;
#ifdef CONFIG_KDB_CONTINUE_CATASTROPHIC
static unsigned int kdb_continue_catastrophic =
CONFIG_KDB_CONTINUE_CATASTROPHIC;
#else
static unsigned int kdb_continue_catastrophic;
#endif
/* kdb_commands describes the available commands. */
static kdbtab_t *kdb_commands;
#define KDB_BASE_CMD_MAX 50
static int kdb_max_commands = KDB_BASE_CMD_MAX;
static kdbtab_t kdb_base_commands[KDB_BASE_CMD_MAX];
#define for_each_kdbcmd(cmd, num) \
for ((cmd) = kdb_base_commands, (num) = 0; \
num < kdb_max_commands; \
num++, num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++)
typedef struct _kdbmsg {
int km_diag; /* kdb diagnostic */
char *km_msg; /* Corresponding message text */
} kdbmsg_t;
#define KDBMSG(msgnum, text) \
{ KDB_##msgnum, text }
static kdbmsg_t kdbmsgs[] = {
KDBMSG(NOTFOUND, "Command Not Found"),
KDBMSG(ARGCOUNT, "Improper argument count, see usage."),
KDBMSG(BADWIDTH, "Illegal value for BYTESPERWORD use 1, 2, 4 or 8, "
"8 is only allowed on 64 bit systems"),
KDBMSG(BADRADIX, "Illegal value for RADIX use 8, 10 or 16"),
KDBMSG(NOTENV, "Cannot find environment variable"),
KDBMSG(NOENVVALUE, "Environment variable should have value"),
KDBMSG(NOTIMP, "Command not implemented"),
KDBMSG(ENVFULL, "Environment full"),
KDBMSG(ENVBUFFULL, "Environment buffer full"),
KDBMSG(TOOMANYBPT, "Too many breakpoints defined"),
#ifdef CONFIG_CPU_XSCALE
KDBMSG(TOOMANYDBREGS, "More breakpoints than ibcr registers defined"),
#else
KDBMSG(TOOMANYDBREGS, "More breakpoints than db registers defined"),
#endif
KDBMSG(DUPBPT, "Duplicate breakpoint address"),
KDBMSG(BPTNOTFOUND, "Breakpoint not found"),
KDBMSG(BADMODE, "Invalid IDMODE"),
KDBMSG(BADINT, "Illegal numeric value"),
KDBMSG(INVADDRFMT, "Invalid symbolic address format"),
KDBMSG(BADREG, "Invalid register name"),
KDBMSG(BADCPUNUM, "Invalid cpu number"),
KDBMSG(BADLENGTH, "Invalid length field"),
KDBMSG(NOBP, "No Breakpoint exists"),
KDBMSG(BADADDR, "Invalid address"),
KDBMSG(NOPERM, "Permission denied"),
};
#undef KDBMSG
static const int __nkdb_err = ARRAY_SIZE(kdbmsgs);
/*
* Initial environment. This is all kept static and local to
* this file. We don't want to rely on the memory allocation
* mechanisms in the kernel, so we use a very limited allocate-only
* heap for new and altered environment variables. The entire
* environment is limited to a fixed number of entries (add more
* to __env[] if required) and a fixed amount of heap (add more to
* KDB_ENVBUFSIZE if required).
*/
static char *__env[] = {
#if defined(CONFIG_SMP)
"PROMPT=[%d]kdb> ",
#else
"PROMPT=kdb> ",
#endif
"MOREPROMPT=more> ",
"RADIX=16",
"MDCOUNT=8", /* lines of md output */
KDB_PLATFORM_ENV,
"DTABCOUNT=30",
"NOSECT=1",
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
};
static const int __nenv = ARRAY_SIZE(__env);
struct task_struct *kdb_curr_task(int cpu)
{
struct task_struct *p = curr_task(cpu);
#ifdef _TIF_MCA_INIT
if ((task_thread_info(p)->flags & _TIF_MCA_INIT) && KDB_TSK(cpu))
p = krp->p;
#endif
return p;
}
/*
* Check whether the flags of the current command and the permissions
* of the kdb console has allow a command to be run.
*/
static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
bool no_args)
{
/* permissions comes from userspace so needs massaging slightly */
permissions &= KDB_ENABLE_MASK;
permissions |= KDB_ENABLE_ALWAYS_SAFE;
/* some commands change group when launched with no arguments */
if (no_args)
permissions |= permissions << KDB_ENABLE_NO_ARGS_SHIFT;
flags |= KDB_ENABLE_ALL;
return permissions & flags;
}
/*
* kdbgetenv - This function will return the character string value of
* an environment variable.
* Parameters:
* match A character string representing an environment variable.
* Returns:
* NULL No environment variable matches 'match'
* char* Pointer to string value of environment variable.
*/
char *kdbgetenv(const char *match)
{
char **ep = __env;
int matchlen = strlen(match);
int i;
for (i = 0; i < __nenv; i++) {
char *e = *ep++;
if (!e)
continue;
if ((strncmp(match, e, matchlen) == 0)
&& ((e[matchlen] == '\0')
|| (e[matchlen] == '='))) {
char *cp = strchr(e, '=');
return cp ? ++cp : "";
}
}
return NULL;
}
/*
* kdballocenv - This function is used to allocate bytes for
* environment entries.
* Parameters:
* match A character string representing a numeric value
* Outputs:
* *value the unsigned long representation of the env variable 'match'
* Returns:
* Zero on success, a kdb diagnostic on failure.
* Remarks:
* We use a static environment buffer (envbuffer) to hold the values
* of dynamically generated environment variables (see kdb_set). Buffer
* space once allocated is never free'd, so over time, the amount of space
* (currently 512 bytes) will be exhausted if env variables are changed
* frequently.
*/
static char *kdballocenv(size_t bytes)
{
#define KDB_ENVBUFSIZE 512
static char envbuffer[KDB_ENVBUFSIZE];
static int envbufsize;
char *ep = NULL;
if ((KDB_ENVBUFSIZE - envbufsize) >= bytes) {
ep = &envbuffer[envbufsize];
envbufsize += bytes;
}
return ep;
}
/*
* kdbgetulenv - This function will return the value of an unsigned
* long-valued environment variable.
* Parameters:
* match A character string representing a numeric value
* Outputs:
* *value the unsigned long represntation of the env variable 'match'
* Returns:
* Zero on success, a kdb diagnostic on failure.
*/
static int kdbgetulenv(const char *match, unsigned long *value)
{
char *ep;
ep = kdbgetenv(match);
if (!ep)
return KDB_NOTENV;
if (strlen(ep) == 0)
return KDB_NOENVVALUE;
*value = simple_strtoul(ep, NULL, 0);
return 0;
}
/*
* kdbgetintenv - This function will return the value of an
* integer-valued environment variable.
* Parameters:
* match A character string representing an integer-valued env variable
* Outputs:
* *value the integer representation of the environment variable 'match'
* Returns:
* Zero on success, a kdb diagnostic on failure.
*/
int kdbgetintenv(const char *match, int *value)
{
unsigned long val;
int diag;
diag = kdbgetulenv(match, &val);
if (!diag)
*value = (int) val;
return diag;
}
/*
* kdbgetularg - This function will convert a numeric string into an
* unsigned long value.
* Parameters:
* arg A character string representing a numeric value
* Outputs:
* *value the unsigned long represntation of arg.
* Returns:
* Zero on success, a kdb diagnostic on failure.
*/
int kdbgetularg(const char *arg, unsigned long *value)
{
char *endp;
unsigned long val;
val = simple_strtoul(arg, &endp, 0);
if (endp == arg) {
/*
* Also try base 16, for us folks too lazy to type the
* leading 0x...
*/
val = simple_strtoul(arg, &endp, 16);
if (endp == arg)
return KDB_BADINT;
}
*value = val;
return 0;
}
int kdbgetu64arg(const char *arg, u64 *value)
{
char *endp;
u64 val;
val = simple_strtoull(arg, &endp, 0);
if (endp == arg) {
val = simple_strtoull(arg, &endp, 16);
if (endp == arg)
return KDB_BADINT;
}
*value = val;
return 0;
}
/*
* kdb_set - This function implements the 'set' command. Alter an
* existing environment variable or create a new one.
*/
int kdb_set(int argc, const char **argv)
{
int i;
char *ep;
size_t varlen, vallen;
/*
* we can be invoked two ways:
* set var=value argv[1]="var", argv[2]="value"
* set var = value argv[1]="var", argv[2]="=", argv[3]="value"
* - if the latter, shift 'em down.
*/
if (argc == 3) {
argv[2] = argv[3];
argc--;
}
if (argc != 2)
return KDB_ARGCOUNT;
/*
* Check for internal variables
*/
if (strcmp(argv[1], "KDBDEBUG") == 0) {
unsigned int debugflags;
char *cp;
debugflags = simple_strtoul(argv[2], &cp, 0);
if (cp == argv[2] || debugflags & ~KDB_DEBUG_FLAG_MASK) {
kdb_printf("kdb: illegal debug flags '%s'\n",
argv[2]);
return 0;
}
kdb_flags = (kdb_flags &
~(KDB_DEBUG_FLAG_MASK << KDB_DEBUG_FLAG_SHIFT))
| (debugflags << KDB_DEBUG_FLAG_SHIFT);
return 0;
}
/*
* Tokenizer squashed the '=' sign. argv[1] is variable
* name, argv[2] = value.
*/
varlen = strlen(argv[1]);
vallen = strlen(argv[2]);
ep = kdballocenv(varlen + vallen + 2);
if (ep == (char *)0)
return KDB_ENVBUFFULL;
sprintf(ep, "%s=%s", argv[1], argv[2]);
ep[varlen+vallen+1] = '\0';
for (i = 0; i < __nenv; i++) {
if (__env[i]
&& ((strncmp(__env[i], argv[1], varlen) == 0)
&& ((__env[i][varlen] == '\0')
|| (__env[i][varlen] == '=')))) {
__env[i] = ep;
return 0;
}
}
/*
* Wasn't existing variable. Fit into slot.
*/
for (i = 0; i < __nenv-1; i++) {
if (__env[i] == (char *)0) {
__env[i] = ep;
return 0;
}
}
return KDB_ENVFULL;
}
static int kdb_check_regs(void)
{
if (!kdb_current_regs) {
kdb_printf("No current kdb registers."
" You may need to select another task\n");
return KDB_BADREG;
}
return 0;
}
/*
* kdbgetaddrarg - This function is responsible for parsing an
* address-expression and returning the value of the expression,
* symbol name, and offset to the caller.
*
* The argument may consist of a numeric value (decimal or
* hexidecimal), a symbol name, a register name (preceded by the
* percent sign), an environment variable with a numeric value
* (preceded by a dollar sign) or a simple arithmetic expression
* consisting of a symbol name, +/-, and a numeric constant value
* (offset).
* Parameters:
* argc - count of arguments in argv
* argv - argument vector
* *nextarg - index to next unparsed argument in argv[]
* regs - Register state at time of KDB entry
* Outputs:
* *value - receives the value of the address-expression
* *offset - receives the offset specified, if any
* *name - receives the symbol name, if any
* *nextarg - index to next unparsed argument in argv[]
* Returns:
* zero is returned on success, a kdb diagnostic code is
* returned on error.
*/
int kdbgetaddrarg(int argc, const char **argv, int *nextarg,
unsigned long *value, long *offset,
char **name)
{
unsigned long addr;
unsigned long off = 0;
int positive;
int diag;
int found = 0;
char *symname;
char symbol = '\0';
char *cp;
kdb_symtab_t symtab;
/*
* If the enable flags prohibit both arbitrary memory access
* and flow control then there are no reasonable grounds to
* provide symbol lookup.
*/
if (!kdb_check_flags(KDB_ENABLE_MEM_READ | KDB_ENABLE_FLOW_CTRL,
kdb_cmd_enabled, false))
return KDB_NOPERM;
/*
* Process arguments which follow the following syntax:
*
* symbol | numeric-address [+/- numeric-offset]
* %register
* $environment-variable
*/
if (*nextarg > argc)
return KDB_ARGCOUNT;
symname = (char *)argv[*nextarg];
/*
* If there is no whitespace between the symbol
* or address and the '+' or '-' symbols, we
* remember the character and replace it with a
* null so the symbol/value can be properly parsed
*/
cp = strpbrk(symname, "+-");
if (cp != NULL) {
symbol = *cp;
*cp++ = '\0';
}
if (symname[0] == '$') {
diag = kdbgetulenv(&symname[1], &addr);
if (diag)
return diag;
} else if (symname[0] == '%') {
diag = kdb_check_regs();
if (diag)
return diag;
/* Implement register values with % at a later time as it is
* arch optional.
*/
return KDB_NOTIMP;
} else {
found = kdbgetsymval(symname, &symtab);
if (found) {
addr = symtab.sym_start;
} else {
diag = kdbgetularg(argv[*nextarg], &addr);
if (diag)
return diag;
}
}
if (!found)
found = kdbnearsym(addr, &symtab);
(*nextarg)++;
if (name)
*name = symname;
if (value)
*value = addr;
if (offset && name && *name)
*offset = addr - symtab.sym_start;
if ((*nextarg > argc)
&& (symbol == '\0'))
return 0;
/*
* check for +/- and offset
*/
if (symbol == '\0') {
if ((argv[*nextarg][0] != '+')
&& (argv[*nextarg][0] != '-')) {
/*
* Not our argument. Return.
*/
return 0;
} else {
positive = (argv[*nextarg][0] == '+');
(*nextarg)++;
}
} else
positive = (symbol == '+');
/*
* Now there must be an offset!
*/
if ((*nextarg > argc)
&& (symbol == '\0')) {
return KDB_INVADDRFMT;
}
if (!symbol) {
cp = (char *)argv[*nextarg];
(*nextarg)++;
}
diag = kdbgetularg(cp, &off);
if (diag)
return diag;
if (!positive)
off = -off;
if (offset)
*offset += off;
if (value)
*value += off;
return 0;
}
static void kdb_cmderror(int diag)
{
int i;
if (diag >= 0) {
kdb_printf("no error detected (diagnostic is %d)\n", diag);
return;
}
for (i = 0; i < __nkdb_err; i++) {
if (kdbmsgs[i].km_diag == diag) {
kdb_printf("diag: %d: %s\n", diag, kdbmsgs[i].km_msg);
return;
}
}
kdb_printf("Unknown diag %d\n", -diag);
}
/*
* kdb_defcmd, kdb_defcmd2 - This function implements the 'defcmd'
* command which defines one command as a set of other commands,
* terminated by endefcmd. kdb_defcmd processes the initial
* 'defcmd' command, kdb_defcmd2 is invoked from kdb_parse for
* the following commands until 'endefcmd'.
* Inputs:
* argc argument count
* argv argument vector
* Returns:
* zero for success, a kdb diagnostic if error
*/
struct defcmd_set {
int count;
int usable;
char *name;
char *usage;
char *help;
char **command;
};
static struct defcmd_set *defcmd_set;
static int defcmd_set_count;
static int defcmd_in_progress;
/* Forward references */
static int kdb_exec_defcmd(int argc, const char **argv);
static int kdb_defcmd2(const char *cmdstr, const char *argv0)
{
struct defcmd_set *s = defcmd_set + defcmd_set_count - 1;
char **save_command = s->command;
if (strcmp(argv0, "endefcmd") == 0) {
defcmd_in_progress = 0;
if (!s->count)
s->usable = 0;
if (s->usable)
/* macros are always safe because when executed each
* internal command re-enters kdb_parse() and is
* safety checked individually.
*/
kdb_register_flags(s->name, kdb_exec_defcmd, s->usage,
s->help, 0,
KDB_ENABLE_ALWAYS_SAFE);
return 0;
}
if (!s->usable)
return KDB_NOTIMP;
s->command = kcalloc(s->count + 1, sizeof(*(s->command)), GFP_KDB);
if (!s->command) {
kdb_printf("Could not allocate new kdb_defcmd table for %s\n",
cmdstr);
s->usable = 0;
return KDB_NOTIMP;
}
memcpy(s->command, save_command, s->count * sizeof(*(s->command)));
s->command[s->count++] = kdb_strdup(cmdstr, GFP_KDB);
kfree(save_command);
return 0;
}
static int kdb_defcmd(int argc, const char **argv)
{
struct defcmd_set *save_defcmd_set = defcmd_set, *s;
if (defcmd_in_progress) {
kdb_printf("kdb: nested defcmd detected, assuming missing "
"endefcmd\n");
kdb_defcmd2("endefcmd", "endefcmd");
}
if (argc == 0) {
int i;
for (s = defcmd_set; s < defcmd_set + defcmd_set_count; ++s) {
kdb_printf("defcmd %s \"%s\" \"%s\"\n", s->name,
s->usage, s->help);
for (i = 0; i < s->count; ++i)
kdb_printf("%s", s->command[i]);
kdb_printf("endefcmd\n");
}
return 0;
}
if (argc != 3)
return KDB_ARGCOUNT;
if (in_dbg_master()) {
kdb_printf("Command only available during kdb_init()\n");
return KDB_NOTIMP;
}
defcmd_set = kmalloc_array(defcmd_set_count + 1, sizeof(*defcmd_set),
GFP_KDB);
if (!defcmd_set)
goto fail_defcmd;
memcpy(defcmd_set, save_defcmd_set,
defcmd_set_count * sizeof(*defcmd_set));
s = defcmd_set + defcmd_set_count;
memset(s, 0, sizeof(*s));
s->usable = 1;
s->name = kdb_strdup(argv[1], GFP_KDB);
if (!s->name)
goto fail_name;
s->usage = kdb_strdup(argv[2], GFP_KDB);
if (!s->usage)
goto fail_usage;
s->help = kdb_strdup(argv[3], GFP_KDB);
if (!s->help)
goto fail_help;
if (s->usage[0] == '"') {
strcpy(s->usage, argv[2]+1);
s->usage[strlen(s->usage)-1] = '\0';
}
if (s->help[0] == '"') {
strcpy(s->help, argv[3]+1);
s->help[strlen(s->help)-1] = '\0';
}
++defcmd_set_count;
defcmd_in_progress = 1;
kfree(save_defcmd_set);
return 0;
fail_help:
kfree(s->usage);
fail_usage:
kfree(s->name);
fail_name:
kfree(defcmd_set);
fail_defcmd:
kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]);
defcmd_set = save_defcmd_set;
return KDB_NOTIMP;
}
/*
* kdb_exec_defcmd - Execute the set of commands associated with this
* defcmd name.
* Inputs:
* argc argument count
* argv argument vector
* Returns:
* zero for success, a kdb diagnostic if error
*/
static int kdb_exec_defcmd(int argc, const char **argv)
{
int i, ret;
struct defcmd_set *s;
if (argc != 0)
return KDB_ARGCOUNT;
for (s = defcmd_set, i = 0; i < defcmd_set_count; ++i, ++s) {
if (strcmp(s->name, argv[0]) == 0)
break;
}
if (i == defcmd_set_count) {
kdb_printf("kdb_exec_defcmd: could not find commands for %s\n",
argv[0]);
return KDB_NOTIMP;
}
for (i = 0; i < s->count; ++i) {
/* Recursive use of kdb_parse, do not use argv after
* this point */
argv = NULL;
kdb_printf("[%s]kdb> %s\n", s->name, s->command[i]);
ret = kdb_parse(s->command[i]);
if (ret)
return ret;
}
return 0;
}
/* Command history */
#define KDB_CMD_HISTORY_COUNT 32
#define CMD_BUFLEN 200 /* kdb_printf: max printline
* size == 256 */
static unsigned int cmd_head, cmd_tail;
static unsigned int cmdptr;
static char cmd_hist[KDB_CMD_HISTORY_COUNT][CMD_BUFLEN];
static char cmd_cur[CMD_BUFLEN];
/*
* The "str" argument may point to something like | grep xyz
*/
static void parse_grep(const char *str)
{
int len;
char *cp = (char *)str, *cp2;
/* sanity check: we should have been called with the \ first */
if (*cp != '|')
return;
cp++;
while (isspace(*cp))
cp++;
if (strncmp(cp, "grep ", 5)) {
kdb_printf("invalid 'pipe', see grephelp\n");
return;
}
cp += 5;
while (isspace(*cp))
cp++;
cp2 = strchr(cp, '\n');
if (cp2)
*cp2 = '\0'; /* remove the trailing newline */
len = strlen(cp);
if (len == 0) {
kdb_printf("invalid 'pipe', see grephelp\n");
return;
}
/* now cp points to a nonzero length search string */
if (*cp == '"') {
/* allow it be "x y z" by removing the "'s - there must
be two of them */
cp++;
cp2 = strchr(cp, '"');
if (!cp2) {
kdb_printf("invalid quoted string, see grephelp\n");
return;
}
*cp2 = '\0'; /* end the string where the 2nd " was */
}
kdb_grep_leading = 0;
if (*cp == '^') {
kdb_grep_leading = 1;
cp++;
}
len = strlen(cp);
kdb_grep_trailing = 0;
if (*(cp+len-1) == '$') {
kdb_grep_trailing = 1;
*(cp+len-1) = '\0';
}
len = strlen(cp);
if (!len)
return;
if (len >= KDB_GREP_STRLEN) {
kdb_printf("search string too long\n");
return;
}
strcpy(kdb_grep_string, cp);
kdb_grepping_flag++;
return;
}
/*
* kdb_parse - Parse the command line, search the command table for a
* matching command and invoke the command function. This
* function may be called recursively, if it is, the second call
* will overwrite argv and cbuf. It is the caller's
* responsibility to save their argv if they recursively call
* kdb_parse().
* Parameters:
* cmdstr The input command line to be parsed.
* regs The registers at the time kdb was entered.
* Returns:
* Zero for success, a kdb diagnostic if failure.
* Remarks:
* Limited to 20 tokens.
*
* Real rudimentary tokenization. Basically only whitespace
* is considered a token delimeter (but special consideration
* is taken of the '=' sign as used by the 'set' command).
*
* The algorithm used to tokenize the input string relies on
* there being at least one whitespace (or otherwise useless)
* character between tokens as the character immediately following
* the token is altered in-place to a null-byte to terminate the
* token string.
*/
#define MAXARGC 20
int kdb_parse(const char *cmdstr)
{
static char *argv[MAXARGC];
static int argc;
static char cbuf[CMD_BUFLEN+2];
char *cp;
char *cpp, quoted;
kdbtab_t *tp;
int i, escaped, ignore_errors = 0, check_grep = 0;
/*
* First tokenize the command string.
*/
cp = (char *)cmdstr;
if (KDB_FLAG(CMD_INTERRUPT)) {
/* Previous command was interrupted, newline must not
* repeat the command */
KDB_FLAG_CLEAR(CMD_INTERRUPT);
KDB_STATE_SET(PAGER);
argc = 0; /* no repeat */
}
if (*cp != '\n' && *cp != '\0') {
argc = 0;
cpp = cbuf;
while (*cp) {
/* skip whitespace */
while (isspace(*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n') ||
(*cp == '#' && !defcmd_in_progress))
break;
/* special case: check for | grep pattern */
if (*cp == '|') {
check_grep++;
break;
}
if (cpp >= cbuf + CMD_BUFLEN) {
kdb_printf("kdb_parse: command buffer "
"overflow, command ignored\n%s\n",
cmdstr);
return KDB_NOTFOUND;
}
if (argc >= MAXARGC - 1) {
kdb_printf("kdb_parse: too many arguments, "
"command ignored\n%s\n", cmdstr);
return KDB_NOTFOUND;
}
argv[argc++] = cpp;
escaped = 0;
quoted = '\0';
/* Copy to next unquoted and unescaped
* whitespace or '=' */
while (*cp && *cp != '\n' &&
(escaped || quoted || !isspace(*cp))) {
if (cpp >= cbuf + CMD_BUFLEN)
break;
if (escaped) {
escaped = 0;
*cpp++ = *cp++;
continue;
}
if (*cp == '\\') {
escaped = 1;
++cp;
continue;
}
if (*cp == quoted)
quoted = '\0';
else if (*cp == '\'' || *cp == '"')
quoted = *cp;
*cpp = *cp++;
if (*cpp == '=' && !quoted)
break;
++cpp;
}
*cpp++ = '\0'; /* Squash a ws or '=' character */
}
}
if (!argc)
return 0;
if (check_grep)
parse_grep(cp);
if (defcmd_in_progress) {
int result = kdb_defcmd2(cmdstr, argv[0]);
if (!defcmd_in_progress) {
argc = 0; /* avoid repeat on endefcmd */
*(argv[0]) = '\0';
}
return result;
}
if (argv[0][0] == '-' && argv[0][1] &&
(argv[0][1] < '0' || argv[0][1] > '9')) {
ignore_errors = 1;
++argv[0];
}
for_each_kdbcmd(tp, i) {
if (tp->cmd_name) {
/*
* If this command is allowed to be abbreviated,
* check to see if this is it.
*/
if (tp->cmd_minlen
&& (strlen(argv[0]) <= tp->cmd_minlen)) {
if (strncmp(argv[0],
tp->cmd_name,
tp->cmd_minlen) == 0) {
break;
}
}
if (strcmp(argv[0], tp->cmd_name) == 0)
break;
}
}
/*
* If we don't find a command by this name, see if the first
* few characters of this match any of the known commands.
* e.g., md1c20 should match md.
*/
if (i == kdb_max_commands) {
for_each_kdbcmd(tp, i) {
if (tp->cmd_name) {
if (strncmp(argv[0],
tp->cmd_name,
strlen(tp->cmd_name)) == 0) {
break;
}
}
}
}
if (i < kdb_max_commands) {
int result;
if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))
return KDB_NOPERM;
KDB_STATE_SET(CMD);
result = (*tp->cmd_func)(argc-1, (const char **)argv);
if (result && ignore_errors && result > KDB_CMD_GO)
result = 0;
KDB_STATE_CLEAR(CMD);
if (tp->cmd_flags & KDB_REPEAT_WITH_ARGS)
return result;
argc = tp->cmd_flags & KDB_REPEAT_NO_ARGS ? 1 : 0;
if (argv[argc])
*(argv[argc]) = '\0';
return result;
}
/*
* If the input with which we were presented does not
* map to an existing command, attempt to parse it as an
* address argument and display the result. Useful for
* obtaining the address of a variable, or the nearest symbol
* to an address contained in a register.
*/
{
unsigned long value;
char *name = NULL;
long offset;
int nextarg = 0;
if (kdbgetaddrarg(0, (const char **)argv, &nextarg,
&value, &offset, &name)) {
return KDB_NOTFOUND;
}
kdb_printf("%s = ", argv[0]);
kdb_symbol_print(value, NULL, KDB_SP_DEFAULT);
kdb_printf("\n");
return 0;
}
}
static int handle_ctrl_cmd(char *cmd)
{
#define CTRL_P 16
#define CTRL_N 14
/* initial situation */
if (cmd_head == cmd_tail)
return 0;
switch (*cmd) {
case CTRL_P:
if (cmdptr != cmd_tail)
cmdptr = (cmdptr-1) % KDB_CMD_HISTORY_COUNT;
strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN);
return 1;
case CTRL_N:
if (cmdptr != cmd_head)
cmdptr = (cmdptr+1) % KDB_CMD_HISTORY_COUNT;
strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN);
return 1;
}
return 0;
}
/*
* kdb_reboot - This function implements the 'reboot' command. Reboot
* the system immediately, or loop for ever on failure.
*/
static int kdb_reboot(int argc, const char **argv)
{
emergency_restart();
kdb_printf("Hmm, kdb_reboot did not reboot, spinning here\n");
while (1)
cpu_relax();
/* NOTREACHED */
return 0;
}
static void kdb_dumpregs(struct pt_regs *regs)
{
int old_lvl = console_loglevel;
console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;
kdb_trap_printk++;
show_regs(regs);
kdb_trap_printk--;
kdb_printf("\n");
console_loglevel = old_lvl;
}
void kdb_set_current_task(struct task_struct *p)
{
kdb_current_task = p;
if (kdb_task_has_cpu(p)) {
kdb_current_regs = KDB_TSKREGS(kdb_process_cpu(p));
return;
}
kdb_current_regs = NULL;
}
static void drop_newline(char *buf)
{
size_t len = strlen(buf);
if (len == 0)
return;
if (*(buf + len - 1) == '\n')
*(buf + len - 1) = '\0';
}
/*
* kdb_local - The main code for kdb. This routine is invoked on a
* specific processor, it is not global. The main kdb() routine
* ensures that only one processor at a time is in this routine.
* This code is called with the real reason code on the first
* entry to a kdb session, thereafter it is called with reason
* SWITCH, even if the user goes back to the original cpu.
* Inputs:
* reason The reason KDB was invoked
* error The hardware-defined error code
* regs The exception frame at time of fault/breakpoint.
* db_result Result code from the break or debug point.
* Returns:
* 0 KDB was invoked for an event which it wasn't responsible
* 1 KDB handled the event for which it was invoked.
* KDB_CMD_GO User typed 'go'.
* KDB_CMD_CPU User switched to another cpu.
* KDB_CMD_SS Single step.
*/
static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
kdb_dbtrap_t db_result)
{
char *cmdbuf;
int diag;
struct task_struct *kdb_current =
kdb_curr_task(raw_smp_processor_id());
KDB_DEBUG_STATE("kdb_local 1", reason);
kdb_go_count = 0;
if (reason == KDB_REASON_DEBUG) {
/* special case below */
} else {
kdb_printf("\nEntering kdb (current=0x%px, pid %d) ",
kdb_current, kdb_current ? kdb_current->pid : 0);
#if defined(CONFIG_SMP)
kdb_printf("on processor %d ", raw_smp_processor_id());
#endif
}
switch (reason) {
case KDB_REASON_DEBUG:
{
/*
* If re-entering kdb after a single step
* command, don't print the message.
*/
switch (db_result) {
case KDB_DB_BPT:
kdb_printf("\nEntering kdb (0x%px, pid %d) ",
kdb_current, kdb_current->pid);
#if defined(CONFIG_SMP)
kdb_printf("on processor %d ", raw_smp_processor_id());
#endif
kdb_printf("due to Debug @ " kdb_machreg_fmt "\n",
instruction_pointer(regs));
break;
case KDB_DB_SS:
break;
case KDB_DB_SSBPT:
KDB_DEBUG_STATE("kdb_local 4", reason);
return 1; /* kdba_db_trap did the work */
default:
kdb_printf("kdb: Bad result from kdba_db_trap: %d\n",
db_result);
break;
}
}
break;
case KDB_REASON_ENTER:
if (KDB_STATE(KEYBOARD))
kdb_printf("due to Keyboard Entry\n");
else
kdb_printf("due to KDB_ENTER()\n");
break;
case KDB_REASON_KEYBOARD:
KDB_STATE_SET(KEYBOARD);
kdb_printf("due to Keyboard Entry\n");
break;
case KDB_REASON_ENTER_SLAVE:
/* drop through, slaves only get released via cpu switch */
case KDB_REASON_SWITCH:
kdb_printf("due to cpu switch\n");
break;
case KDB_REASON_OOPS:
kdb_printf("Oops: %s\n", kdb_diemsg);
kdb_printf("due to oops @ " kdb_machreg_fmt "\n",
instruction_pointer(regs));
kdb_dumpregs(regs);
break;
case KDB_REASON_SYSTEM_NMI:
kdb_printf("due to System NonMaskable Interrupt\n");
break;
case KDB_REASON_NMI:
kdb_printf("due to NonMaskable Interrupt @ "
kdb_machreg_fmt "\n",
instruction_pointer(regs));
break;
case KDB_REASON_SSTEP:
case KDB_REASON_BREAK:
kdb_printf("due to %s @ " kdb_machreg_fmt "\n",
reason == KDB_REASON_BREAK ?
"Breakpoint" : "SS trap", instruction_pointer(regs));
/*
* Determine if this breakpoint is one that we
* are interested in.
*/
if (db_result != KDB_DB_BPT) {
kdb_printf("kdb: error return from kdba_bp_trap: %d\n",
db_result);
KDB_DEBUG_STATE("kdb_local 6", reason);
return 0; /* Not for us, dismiss it */
}
break;
case KDB_REASON_RECURSE:
kdb_printf("due to Recursion @ " kdb_machreg_fmt "\n",
instruction_pointer(regs));
break;
default:
kdb_printf("kdb: unexpected reason code: %d\n", reason);
KDB_DEBUG_STATE("kdb_local 8", reason);
return 0; /* Not for us, dismiss it */
}
while (1) {
/*
* Initialize pager context.
*/
kdb_nextline = 1;
KDB_STATE_CLEAR(SUPPRESS);
kdb_grepping_flag = 0;
/* ensure the old search does not leak into '/' commands */
kdb_grep_string[0] = '\0';
cmdbuf = cmd_cur;
*cmdbuf = '\0';
*(cmd_hist[cmd_head]) = '\0';
do_full_getstr:
#if defined(CONFIG_SMP)
snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"),
raw_smp_processor_id());
#else
snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"));
#endif
if (defcmd_in_progress)
strncat(kdb_prompt_str, "[defcmd]", CMD_BUFLEN);
/*
* Fetch command from keyboard
*/
cmdbuf = kdb_getstr(cmdbuf, CMD_BUFLEN, kdb_prompt_str);
if (*cmdbuf != '\n') {
if (*cmdbuf < 32) {
if (cmdptr == cmd_head) {
strncpy(cmd_hist[cmd_head], cmd_cur,
CMD_BUFLEN);
*(cmd_hist[cmd_head] +
strlen(cmd_hist[cmd_head])-1) = '\0';
}
if (!handle_ctrl_cmd(cmdbuf))
*(cmd_cur+strlen(cmd_cur)-1) = '\0';
cmdbuf = cmd_cur;
goto do_full_getstr;
} else {
strncpy(cmd_hist[cmd_head], cmd_cur,
CMD_BUFLEN);
}
cmd_head = (cmd_head+1) % KDB_CMD_HISTORY_COUNT;
if (cmd_head == cmd_tail)
cmd_tail = (cmd_tail+1) % KDB_CMD_HISTORY_COUNT;
}
cmdptr = cmd_head;
diag = kdb_parse(cmdbuf);
if (diag == KDB_NOTFOUND) {
drop_newline(cmdbuf);
kdb_printf("Unknown kdb command: '%s'\n", cmdbuf);
diag = 0;
}
if (diag == KDB_CMD_GO
|| diag == KDB_CMD_CPU
|| diag == KDB_CMD_SS
|| diag == KDB_CMD_KGDB)
break;
if (diag)
kdb_cmderror(diag);
}
KDB_DEBUG_STATE("kdb_local 9", diag);
return diag;
}
/*
* kdb_print_state - Print the state data for the current processor
* for debugging.
* Inputs:
* text Identifies the debug point
* value Any integer value to be printed, e.g. reason code.
*/
void kdb_print_state(const char *text, int value)
{
kdb_printf("state: %s cpu %d value %d initial %d state %x\n",
text, raw_smp_processor_id(), value, kdb_initial_cpu,
kdb_state);
}
/*
* kdb_main_loop - After initial setup and assignment of the
* controlling cpu, all cpus are in this loop. One cpu is in
* control and will issue the kdb prompt, the others will spin
* until 'go' or cpu switch.
*
* To get a consistent view of the kernel stacks for all
* processes, this routine is invoked from the main kdb code via
* an architecture specific routine. kdba_main_loop is
* responsible for making the kernel stacks consistent for all
* processes, there should be no difference between a blocked
* process and a running process as far as kdb is concerned.
* Inputs:
* reason The reason KDB was invoked
* error The hardware-defined error code
* reason2 kdb's current reason code.
* Initially error but can change
* according to kdb state.
* db_result Result code from break or debug point.
* regs The exception frame at time of fault/breakpoint.
* should always be valid.
* Returns:
* 0 KDB was invoked for an event which it wasn't responsible
* 1 KDB handled the event for which it was invoked.
*/
int kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
kdb_dbtrap_t db_result, struct pt_regs *regs)
{
int result = 1;
/* Stay in kdb() until 'go', 'ss[b]' or an error */
while (1) {
/*
* All processors except the one that is in control
* will spin here.
*/
KDB_DEBUG_STATE("kdb_main_loop 1", reason);
while (KDB_STATE(HOLD_CPU)) {
/* state KDB is turned off by kdb_cpu to see if the
* other cpus are still live, each cpu in this loop
* turns it back on.
*/
if (!KDB_STATE(KDB))
KDB_STATE_SET(KDB);
}
KDB_STATE_CLEAR(SUPPRESS);
KDB_DEBUG_STATE("kdb_main_loop 2", reason);
if (KDB_STATE(LEAVING))
break; /* Another cpu said 'go' */
/* Still using kdb, this processor is in control */
result = kdb_local(reason2, error, regs, db_result);
KDB_DEBUG_STATE("kdb_main_loop 3", result);
if (result == KDB_CMD_CPU)
break;
if (result == KDB_CMD_SS) {
KDB_STATE_SET(DOING_SS);
break;
}
if (result == KDB_CMD_KGDB) {
if (!KDB_STATE(DOING_KGDB))
kdb_printf("Entering please attach debugger "
"or use $D#44+ or $3#33\n");
break;
}
if (result && result != 1 && result != KDB_CMD_GO)
kdb_printf("\nUnexpected kdb_local return code %d\n",
result);
KDB_DEBUG_STATE("kdb_main_loop 4", reason);
break;
}
if (KDB_STATE(DOING_SS))
KDB_STATE_CLEAR(SSBPT);
/* Clean up any keyboard devices before leaving */
kdb_kbd_cleanup_state();
return result;
}
/*
* kdb_mdr - This function implements the guts of the 'mdr', memory
* read command.
* mdr <addr arg>,<byte count>
* Inputs:
* addr Start address
* count Number of bytes
* Returns:
* Always 0. Any errors are detected and printed by kdb_getarea.
*/
static int kdb_mdr(unsigned long addr, unsigned int count)
{
unsigned char c;
while (count--) {
if (kdb_getarea(c, addr))
return 0;
kdb_printf("%02x", c);
addr++;
}
kdb_printf("\n");
return 0;
}
/*
* kdb_md - This function implements the 'md', 'md1', 'md2', 'md4',
* 'md8' 'mdr' and 'mds' commands.
*
* md|mds [<addr arg> [<line count> [<radix>]]]
* mdWcN [<addr arg> [<line count> [<radix>]]]
* where W = is the width (1, 2, 4 or 8) and N is the count.
* for eg., md1c20 reads 20 bytes, 1 at a time.
* mdr <addr arg>,<byte count>
*/
static void kdb_md_line(const char *fmtstr, unsigned long addr,
int symbolic, int nosect, int bytesperword,
int num, int repeat, int phys)
{
/* print just one line of data */
kdb_symtab_t symtab;
char cbuf[32];
char *c = cbuf;
int i;
unsigned long word;
memset(cbuf, '\0', sizeof(cbuf));
if (phys)
kdb_printf("phys " kdb_machreg_fmt0 " ", addr);
else
kdb_printf(kdb_machreg_fmt0 " ", addr);
for (i = 0; i < num && repeat--; i++) {
if (phys) {
if (kdb_getphysword(&word, addr, bytesperword))
break;
} else if (kdb_getword(&word, addr, bytesperword))
break;
kdb_printf(fmtstr, word);
if (symbolic)
kdbnearsym(word, &symtab);
else
memset(&symtab, 0, sizeof(symtab));
if (symtab.sym_name) {
kdb_symbol_print(word, &symtab, 0);
if (!nosect) {
kdb_printf("\n");
kdb_printf(" %s %s "
kdb_machreg_fmt " "
kdb_machreg_fmt " "
kdb_machreg_fmt, symtab.mod_name,
symtab.sec_name, symtab.sec_start,
symtab.sym_start, symtab.sym_end);
}
addr += bytesperword;
} else {
union {
u64 word;
unsigned char c[8];
} wc;
unsigned char *cp;
#ifdef __BIG_ENDIAN
cp = wc.c + 8 - bytesperword;
#else
cp = wc.c;
#endif
wc.word = word;
#define printable_char(c) \
({unsigned char __c = c; isascii(__c) && isprint(__c) ? __c : '.'; })
switch (bytesperword) {
case 8:
*c++ = printable_char(*cp++);
*c++ = printable_char(*cp++);
*c++ = printable_char(*cp++);
*c++ = printable_char(*cp++);
addr += 4;
case 4:
*c++ = printable_char(*cp++);
*c++ = printable_char(*cp++);
addr += 2;
case 2:
*c++ = printable_char(*cp++);
addr++;
case 1:
*c++ = printable_char(*cp++);
addr++;
break;
}
#undef printable_char
}
}
kdb_printf("%*s %s\n", (int)((num-i)*(2*bytesperword + 1)+1),
" ", cbuf);
}
static int kdb_md(int argc, const char **argv)
{
static unsigned long last_addr;
static int last_radix, last_bytesperword, last_repeat;
int radix = 16, mdcount = 8, bytesperword = KDB_WORD_SIZE, repeat;
int nosect = 0;
char fmtchar, fmtstr[64];
unsigned long addr;
unsigned long word;
long offset = 0;
int symbolic = 0;
int valid = 0;
int phys = 0;
int raw = 0;
kdbgetintenv("MDCOUNT", &mdcount);
kdbgetintenv("RADIX", &radix);
kdbgetintenv("BYTESPERWORD", &bytesperword);
/* Assume 'md <addr>' and start with environment values */
repeat = mdcount * 16 / bytesperword;
if (strcmp(argv[0], "mdr") == 0) {
if (argc == 2 || (argc == 0 && last_addr != 0))
valid = raw = 1;
else
return KDB_ARGCOUNT;
} else if (isdigit(argv[0][2])) {
bytesperword = (int)(argv[0][2] - '0');
if (bytesperword == 0) {
bytesperword = last_bytesperword;
if (bytesperword == 0)
bytesperword = 4;
}
last_bytesperword = bytesperword;
repeat = mdcount * 16 / bytesperword;
if (!argv[0][3])
valid = 1;
else if (argv[0][3] == 'c' && argv[0][4]) {
char *p;
repeat = simple_strtoul(argv[0] + 4, &p, 10);
mdcount = ((repeat * bytesperword) + 15) / 16;
valid = !*p;
}
last_repeat = repeat;
} else if (strcmp(argv[0], "md") == 0)
valid = 1;
else if (strcmp(argv[0], "mds") == 0)
valid = 1;
else if (strcmp(argv[0], "mdp") == 0) {
phys = valid = 1;
}
if (!valid)
return KDB_NOTFOUND;
if (argc == 0) {
if (last_addr == 0)
return KDB_ARGCOUNT;
addr = last_addr;
radix = last_radix;
bytesperword = last_bytesperword;
repeat = last_repeat;
if (raw)
mdcount = repeat;
else
mdcount = ((repeat * bytesperword) + 15) / 16;
}
if (argc) {
unsigned long val;
int diag, nextarg = 1;
diag = kdbgetaddrarg(argc, argv, &nextarg, &addr,
&offset, NULL);
if (diag)
return diag;
if (argc > nextarg+2)
return KDB_ARGCOUNT;
if (argc >= nextarg) {
diag = kdbgetularg(argv[nextarg], &val);
if (!diag) {
mdcount = (int) val;
if (raw)
repeat = mdcount;
else
repeat = mdcount * 16 / bytesperword;
}
}
if (argc >= nextarg+1) {
diag = kdbgetularg(argv[nextarg+1], &val);
if (!diag)
radix = (int) val;
}
}
if (strcmp(argv[0], "mdr") == 0) {
int ret;
last_addr = addr;
ret = kdb_mdr(addr, mdcount);
last_addr += mdcount;
last_repeat = mdcount;
last_bytesperword = bytesperword; // to make REPEAT happy
return ret;
}
switch (radix) {
case 10:
fmtchar = 'd';
break;
case 16:
fmtchar = 'x';
break;
case 8:
fmtchar = 'o';
break;
default:
return KDB_BADRADIX;
}
last_radix = radix;
if (bytesperword > KDB_WORD_SIZE)
return KDB_BADWIDTH;
switch (bytesperword) {
case 8:
sprintf(fmtstr, "%%16.16l%c ", fmtchar);
break;
case 4:
sprintf(fmtstr, "%%8.8l%c ", fmtchar);
break;
case 2:
sprintf(fmtstr, "%%4.4l%c ", fmtchar);
break;
case 1:
sprintf(fmtstr, "%%2.2l%c ", fmtchar);
break;
default:
return KDB_BADWIDTH;
}
last_repeat = repeat;
last_bytesperword = bytesperword;
if (strcmp(argv[0], "mds") == 0) {
symbolic = 1;
/* Do not save these changes as last_*, they are temporary mds
* overrides.
*/
bytesperword = KDB_WORD_SIZE;
repeat = mdcount;
kdbgetintenv("NOSECT", &nosect);
}
/* Round address down modulo BYTESPERWORD */
addr &= ~(bytesperword-1);
while (repeat > 0) {
unsigned long a;
int n, z, num = (symbolic ? 1 : (16 / bytesperword));
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
for (a = addr, z = 0; z < repeat; a += bytesperword, ++z) {
if (phys) {
if (kdb_getphysword(&word, a, bytesperword)
|| word)
break;
} else if (kdb_getword(&word, a, bytesperword) || word)
break;
}
n = min(num, repeat);
kdb_md_line(fmtstr, addr, symbolic, nosect, bytesperword,
num, repeat, phys);
addr += bytesperword * n;
repeat -= n;
z = (z + num - 1) / num;
if (z > 2) {
int s = num * (z-2);
kdb_printf(kdb_machreg_fmt0 "-" kdb_machreg_fmt0
" zero suppressed\n",
addr, addr + bytesperword * s - 1);
addr += bytesperword * s;
repeat -= s;
}
}
last_addr = addr;
return 0;
}
/*
* kdb_mm - This function implements the 'mm' command.
* mm address-expression new-value
* Remarks:
* mm works on machine words, mmW works on bytes.
*/
static int kdb_mm(int argc, const char **argv)
{
int diag;
unsigned long addr;
long offset = 0;
unsigned long contents;
int nextarg;
int width;
if (argv[0][2] && !isdigit(argv[0][2]))
return KDB_NOTFOUND;
if (argc < 2)
return KDB_ARGCOUNT;
nextarg = 1;
diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
if (diag)
return diag;
if (nextarg > argc)
return KDB_ARGCOUNT;
diag = kdbgetaddrarg(argc, argv, &nextarg, &contents, NULL, NULL);
if (diag)
return diag;
if (nextarg != argc + 1)
return KDB_ARGCOUNT;
width = argv[0][2] ? (argv[0][2] - '0') : (KDB_WORD_SIZE);
diag = kdb_putword(addr, contents, width);
if (diag)
return diag;
kdb_printf(kdb_machreg_fmt " = " kdb_machreg_fmt "\n", addr, contents);
return 0;
}
/*
* kdb_go - This function implements the 'go' command.
* go [address-expression]
*/
static int kdb_go(int argc, const char **argv)
{
unsigned long addr;
int diag;
int nextarg;
long offset;
if (raw_smp_processor_id() != kdb_initial_cpu) {
kdb_printf("go must execute on the entry cpu, "
"please use \"cpu %d\" and then execute go\n",
kdb_initial_cpu);
return KDB_BADCPUNUM;
}
if (argc == 1) {
nextarg = 1;
diag = kdbgetaddrarg(argc, argv, &nextarg,
&addr, &offset, NULL);
if (diag)
return diag;
} else if (argc) {
return KDB_ARGCOUNT;
}
diag = KDB_CMD_GO;
if (KDB_FLAG(CATASTROPHIC)) {
kdb_printf("Catastrophic error detected\n");
kdb_printf("kdb_continue_catastrophic=%d, ",
kdb_continue_catastrophic);
if (kdb_continue_catastrophic == 0 && kdb_go_count++ == 0) {
kdb_printf("type go a second time if you really want "
"to continue\n");
return 0;
}
if (kdb_continue_catastrophic == 2) {
kdb_printf("forcing reboot\n");
kdb_reboot(0, NULL);
}
kdb_printf("attempting to continue\n");
}
return diag;
}
/*
* kdb_rd - This function implements the 'rd' command.
*/
static int kdb_rd(int argc, const char **argv)
{
int len = kdb_check_regs();
#if DBG_MAX_REG_NUM > 0
int i;
char *rname;
int rsize;
u64 reg64;
u32 reg32;
u16 reg16;
u8 reg8;
if (len)
return len;
for (i = 0; i < DBG_MAX_REG_NUM; i++) {
rsize = dbg_reg_def[i].size * 2;
if (rsize > 16)
rsize = 2;
if (len + strlen(dbg_reg_def[i].name) + 4 + rsize > 80) {
len = 0;
kdb_printf("\n");
}
if (len)
len += kdb_printf(" ");
switch(dbg_reg_def[i].size * 8) {
case 8:
rname = dbg_get_reg(i, &reg8, kdb_current_regs);
if (!rname)
break;
len += kdb_printf("%s: %02x", rname, reg8);
break;
case 16:
rname = dbg_get_reg(i, &reg16, kdb_current_regs);
if (!rname)
break;
len += kdb_printf("%s: %04x", rname, reg16);
break;
case 32:
rname = dbg_get_reg(i, &reg32, kdb_current_regs);
if (!rname)
break;
len += kdb_printf("%s: %08x", rname, reg32);
break;
case 64:
rname = dbg_get_reg(i, &reg64, kdb_current_regs);
if (!rname)
break;
len += kdb_printf("%s: %016llx", rname, reg64);
break;
default:
len += kdb_printf("%s: ??", dbg_reg_def[i].name);
}
}
kdb_printf("\n");
#else
if (len)
return len;
kdb_dumpregs(kdb_current_regs);
#endif
return 0;
}
/*
* kdb_rm - This function implements the 'rm' (register modify) command.
* rm register-name new-contents
* Remarks:
* Allows register modification with the same restrictions as gdb
*/
static int kdb_rm(int argc, const char **argv)
{
#if DBG_MAX_REG_NUM > 0
int diag;
const char *rname;
int i;
u64 reg64;
u32 reg32;
u16 reg16;
u8 reg8;
if (argc != 2)
return KDB_ARGCOUNT;
/*
* Allow presence or absence of leading '%' symbol.
*/
rname = argv[1];
if (*rname == '%')
rname++;
diag = kdbgetu64arg(argv[2], &reg64);
if (diag)
return diag;
diag = kdb_check_regs();
if (diag)
return diag;
diag = KDB_BADREG;
for (i = 0; i < DBG_MAX_REG_NUM; i++) {
if (strcmp(rname, dbg_reg_def[i].name) == 0) {
diag = 0;
break;
}
}
if (!diag) {
switch(dbg_reg_def[i].size * 8) {
case 8:
reg8 = reg64;
dbg_set_reg(i, &reg8, kdb_current_regs);
break;
case 16:
reg16 = reg64;
dbg_set_reg(i, &reg16, kdb_current_regs);
break;
case 32:
reg32 = reg64;
dbg_set_reg(i, &reg32, kdb_current_regs);
break;
case 64:
dbg_set_reg(i, &reg64, kdb_current_regs);
break;
}
}
return diag;
#else
kdb_printf("ERROR: Register set currently not implemented\n");
return 0;
#endif
}
#if defined(CONFIG_MAGIC_SYSRQ)
/*
* kdb_sr - This function implements the 'sr' (SYSRQ key) command
* which interfaces to the soi-disant MAGIC SYSRQ functionality.
* sr <magic-sysrq-code>
*/
static int kdb_sr(int argc, const char **argv)
{
bool check_mask =
!kdb_check_flags(KDB_ENABLE_ALL, kdb_cmd_enabled, false);
if (argc != 1)
return KDB_ARGCOUNT;
kdb_trap_printk++;
__handle_sysrq(*argv[1], check_mask);
kdb_trap_printk--;
return 0;
}
#endif /* CONFIG_MAGIC_SYSRQ */
/*
* kdb_ef - This function implements the 'regs' (display exception
* frame) command. This command takes an address and expects to
* find an exception frame at that address, formats and prints
* it.
* regs address-expression
* Remarks:
* Not done yet.
*/
static int kdb_ef(int argc, const char **argv)
{
int diag;
unsigned long addr;
long offset;
int nextarg;
if (argc != 1)
return KDB_ARGCOUNT;
nextarg = 1;
diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
if (diag)
return diag;
show_regs((struct pt_regs *)addr);
return 0;
}
#if defined(CONFIG_MODULES)
/*
* kdb_lsmod - This function implements the 'lsmod' command. Lists
* currently loaded kernel modules.
* Mostly taken from userland lsmod.
*/
static int kdb_lsmod(int argc, const char **argv)
{
struct module *mod;
if (argc != 0)
return KDB_ARGCOUNT;
kdb_printf("Module Size modstruct Used by\n");
list_for_each_entry(mod, kdb_modules, list) {
if (mod->state == MODULE_STATE_UNFORMED)
continue;
kdb_printf("%-20s%8u 0x%px ", mod->name,
mod->core_layout.size, (void *)mod);
#ifdef CONFIG_MODULE_UNLOAD
kdb_printf("%4d ", module_refcount(mod));
#endif
if (mod->state == MODULE_STATE_GOING)
kdb_printf(" (Unloading)");
else if (mod->state == MODULE_STATE_COMING)
kdb_printf(" (Loading)");
else
kdb_printf(" (Live)");
kdb_printf(" 0x%px", mod->core_layout.base);
#ifdef CONFIG_MODULE_UNLOAD
{
struct module_use *use;
kdb_printf(" [ ");
list_for_each_entry(use, &mod->source_list,
source_list)
kdb_printf("%s ", use->target->name);
kdb_printf("]\n");
}
#endif
}
return 0;
}
#endif /* CONFIG_MODULES */
/*
* kdb_env - This function implements the 'env' command. Display the
* current environment variables.
*/
static int kdb_env(int argc, const char **argv)
{
int i;
for (i = 0; i < __nenv; i++) {
if (__env[i])
kdb_printf("%s\n", __env[i]);
}
if (KDB_DEBUG(MASK))
kdb_printf("KDBFLAGS=0x%x\n", kdb_flags);
return 0;
}
#ifdef CONFIG_PRINTK
/*
* kdb_dmesg - This function implements the 'dmesg' command to display
* the contents of the syslog buffer.
* dmesg [lines] [adjust]
*/
static int kdb_dmesg(int argc, const char **argv)
{
int diag;
int logging;
int lines = 0;
int adjust = 0;
int n = 0;
int skip = 0;
struct kmsg_dumper dumper = { .active = 1 };
size_t len;
char buf[201];
if (argc > 2)
return KDB_ARGCOUNT;
if (argc) {
char *cp;
lines = simple_strtol(argv[1], &cp, 0);
if (*cp)
lines = 0;
if (argc > 1) {
adjust = simple_strtoul(argv[2], &cp, 0);
if (*cp || adjust < 0)
adjust = 0;
}
}
/* disable LOGGING if set */
diag = kdbgetintenv("LOGGING", &logging);
if (!diag && logging) {
const char *setargs[] = { "set", "LOGGING", "0" };
kdb_set(2, setargs);
}
kmsg_dump_rewind_nolock(&dumper);
while (kmsg_dump_get_line_nolock(&dumper, 1, NULL, 0, NULL))
n++;
if (lines < 0) {
if (adjust >= n)
kdb_printf("buffer only contains %d lines, nothing "
"printed\n", n);
else if (adjust - lines >= n)
kdb_printf("buffer only contains %d lines, last %d "
"lines printed\n", n, n - adjust);
skip = adjust;
lines = abs(lines);
} else if (lines > 0) {
skip = n - lines - adjust;
lines = abs(lines);
if (adjust >= n) {
kdb_printf("buffer only contains %d lines, "
"nothing printed\n", n);
skip = n;
} else if (skip < 0) {
lines += skip;
skip = 0;
kdb_printf("buffer only contains %d lines, first "
"%d lines printed\n", n, lines);
}
} else {
lines = n;
}
if (skip >= n || skip < 0)
return 0;
kmsg_dump_rewind_nolock(&dumper);
while (kmsg_dump_get_line_nolock(&dumper, 1, buf, sizeof(buf), &len)) {
if (skip) {
skip--;
continue;
}
if (!lines--)
break;
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
kdb_printf("%.*s\n", (int)len - 1, buf);
}
return 0;
}
#endif /* CONFIG_PRINTK */
/* Make sure we balance enable/disable calls, must disable first. */
static atomic_t kdb_nmi_disabled;
static int kdb_disable_nmi(int argc, const char *argv[])
{
if (atomic_read(&kdb_nmi_disabled))
return 0;
atomic_set(&kdb_nmi_disabled, 1);
arch_kgdb_ops.enable_nmi(0);
return 0;
}
static int kdb_param_enable_nmi(const char *val, const struct kernel_param *kp)
{
if (!atomic_add_unless(&kdb_nmi_disabled, -1, 0))
return -EINVAL;
arch_kgdb_ops.enable_nmi(1);
return 0;
}
static const struct kernel_param_ops kdb_param_ops_enable_nmi = {
.set = kdb_param_enable_nmi,
};
module_param_cb(enable_nmi, &kdb_param_ops_enable_nmi, NULL, 0600);
/*
* kdb_cpu - This function implements the 'cpu' command.
* cpu [<cpunum>]
* Returns:
* KDB_CMD_CPU for success, a kdb diagnostic if error
*/
static void kdb_cpu_status(void)
{
int i, start_cpu, first_print = 1;
char state, prev_state = '?';
kdb_printf("Currently on cpu %d\n", raw_smp_processor_id());
kdb_printf("Available cpus: ");
for (start_cpu = -1, i = 0; i < NR_CPUS; i++) {
if (!cpu_online(i)) {
state = 'F'; /* cpu is offline */
} else if (!kgdb_info[i].enter_kgdb) {
state = 'D'; /* cpu is online but unresponsive */
} else {
state = ' '; /* cpu is responding to kdb */
if (kdb_task_state_char(KDB_TSK(i)) == 'I')
state = 'I'; /* idle task */
}
if (state != prev_state) {
if (prev_state != '?') {
if (!first_print)
kdb_printf(", ");
first_print = 0;
kdb_printf("%d", start_cpu);
if (start_cpu < i-1)
kdb_printf("-%d", i-1);
if (prev_state != ' ')
kdb_printf("(%c)", prev_state);
}
prev_state = state;
start_cpu = i;
}
}
/* print the trailing cpus, ignoring them if they are all offline */
if (prev_state != 'F') {
if (!first_print)
kdb_printf(", ");
kdb_printf("%d", start_cpu);
if (start_cpu < i-1)
kdb_printf("-%d", i-1);
if (prev_state != ' ')
kdb_printf("(%c)", prev_state);
}
kdb_printf("\n");
}
static int kdb_cpu(int argc, const char **argv)
{
unsigned long cpunum;
int diag;
if (argc == 0) {
kdb_cpu_status();
return 0;
}
if (argc != 1)
return KDB_ARGCOUNT;
diag = kdbgetularg(argv[1], &cpunum);
if (diag)
return diag;
/*
* Validate cpunum
*/
if ((cpunum >= CONFIG_NR_CPUS) || !kgdb_info[cpunum].enter_kgdb)
return KDB_BADCPUNUM;
dbg_switch_cpu = cpunum;
/*
* Switch to other cpu
*/
return KDB_CMD_CPU;
}
/* The user may not realize that ps/bta with no parameters does not print idle
* or sleeping system daemon processes, so tell them how many were suppressed.
*/
void kdb_ps_suppressed(void)
{
int idle = 0, daemon = 0;
unsigned long mask_I = kdb_task_state_string("I"),
mask_M = kdb_task_state_string("M");
unsigned long cpu;
const struct task_struct *p, *g;
for_each_online_cpu(cpu) {
p = kdb_curr_task(cpu);
if (kdb_task_state(p, mask_I))
++idle;
}
kdb_do_each_thread(g, p) {
if (kdb_task_state(p, mask_M))
++daemon;
} kdb_while_each_thread(g, p);
if (idle || daemon) {
if (idle)
kdb_printf("%d idle process%s (state I)%s\n",
idle, idle == 1 ? "" : "es",
daemon ? " and " : "");
if (daemon)
kdb_printf("%d sleeping system daemon (state M) "
"process%s", daemon,
daemon == 1 ? "" : "es");
kdb_printf(" suppressed,\nuse 'ps A' to see all.\n");
}
}
/*
* kdb_ps - This function implements the 'ps' command which shows a
* list of the active processes.
* ps [DRSTCZEUIMA] All processes, optionally filtered by state
*/
void kdb_ps1(const struct task_struct *p)
{
int cpu;
unsigned long tmp;
if (!p || probe_kernel_read(&tmp, (char *)p, sizeof(unsigned long)))
return;
cpu = kdb_process_cpu(p);
kdb_printf("0x%px %8d %8d %d %4d %c 0x%px %c%s\n",
(void *)p, p->pid, p->parent->pid,
kdb_task_has_cpu(p), kdb_process_cpu(p),
kdb_task_state_char(p),
(void *)(&p->thread),
p == kdb_curr_task(raw_smp_processor_id()) ? '*' : ' ',
p->comm);
if (kdb_task_has_cpu(p)) {
if (!KDB_TSK(cpu)) {
kdb_printf(" Error: no saved data for this cpu\n");
} else {
if (KDB_TSK(cpu) != p)
kdb_printf(" Error: does not match running "
"process table (0x%px)\n", KDB_TSK(cpu));
}
}
}
static int kdb_ps(int argc, const char **argv)
{
struct task_struct *g, *p;
unsigned long mask, cpu;
if (argc == 0)
kdb_ps_suppressed();
kdb_printf("%-*s Pid Parent [*] cpu State %-*s Command\n",
(int)(2*sizeof(void *))+2, "Task Addr",
(int)(2*sizeof(void *))+2, "Thread");
mask = kdb_task_state_string(argc ? argv[1] : NULL);
/* Run the active tasks first */
for_each_online_cpu(cpu) {
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
p = kdb_curr_task(cpu);
if (kdb_task_state(p, mask))
kdb_ps1(p);
}
kdb_printf("\n");
/* Now the real tasks */
kdb_do_each_thread(g, p) {
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
if (kdb_task_state(p, mask))
kdb_ps1(p);
} kdb_while_each_thread(g, p);
return 0;
}
/*
* kdb_pid - This function implements the 'pid' command which switches
* the currently active process.
* pid [<pid> | R]
*/
static int kdb_pid(int argc, const char **argv)
{
struct task_struct *p;
unsigned long val;
int diag;
if (argc > 1)
return KDB_ARGCOUNT;
if (argc) {
if (strcmp(argv[1], "R") == 0) {
p = KDB_TSK(kdb_initial_cpu);
} else {
diag = kdbgetularg(argv[1], &val);
if (diag)
return KDB_BADINT;
p = find_task_by_pid_ns((pid_t)val, &init_pid_ns);
if (!p) {
kdb_printf("No task with pid=%d\n", (pid_t)val);
return 0;
}
}
kdb_set_current_task(p);
}
kdb_printf("KDB current process is %s(pid=%d)\n",
kdb_current_task->comm,
kdb_current_task->pid);
return 0;
}
static int kdb_kgdb(int argc, const char **argv)
{
return KDB_CMD_KGDB;
}
/*
* kdb_help - This function implements the 'help' and '?' commands.
*/
static int kdb_help(int argc, const char **argv)
{
kdbtab_t *kt;
int i;
kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
kdb_printf("-----------------------------"
"-----------------------------\n");
for_each_kdbcmd(kt, i) {
char *space = "";
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
if (!kt->cmd_name)
continue;
if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true))
continue;
if (strlen(kt->cmd_usage) > 20)
space = "\n ";
kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name,
kt->cmd_usage, space, kt->cmd_help);
}
return 0;
}
/*
* kdb_kill - This function implements the 'kill' commands.
*/
static int kdb_kill(int argc, const char **argv)
{
long sig, pid;
char *endp;
struct task_struct *p;
if (argc != 2)
return KDB_ARGCOUNT;
sig = simple_strtol(argv[1], &endp, 0);
if (*endp)
return KDB_BADINT;
if ((sig >= 0) || !valid_signal(-sig)) {
kdb_printf("Invalid signal parameter.<-signal>\n");
return 0;
}
sig = -sig;
pid = simple_strtol(argv[2], &endp, 0);
if (*endp)
return KDB_BADINT;
if (pid <= 0) {
kdb_printf("Process ID must be large than 0.\n");
return 0;
}
/* Find the process. */
p = find_task_by_pid_ns(pid, &init_pid_ns);
if (!p) {
kdb_printf("The specified process isn't found.\n");
return 0;
}
p = p->group_leader;
kdb_send_sig(p, sig);
return 0;
}
/*
* Most of this code has been lifted from kernel/timer.c::sys_sysinfo().
* I cannot call that code directly from kdb, it has an unconditional
* cli()/sti() and calls routines that take locks which can stop the debugger.
*/
static void kdb_sysinfo(struct sysinfo *val)
{
u64 uptime = ktime_get_mono_fast_ns();
memset(val, 0, sizeof(*val));
val->uptime = div_u64(uptime, NSEC_PER_SEC);
val->loads[0] = avenrun[0];
val->loads[1] = avenrun[1];
val->loads[2] = avenrun[2];
val->procs = nr_threads-1;
si_meminfo(val);
return;
}
/*
* kdb_summary - This function implements the 'summary' command.
*/
static int kdb_summary(int argc, const char **argv)
{
time64_t now;
struct tm tm;
struct sysinfo val;
if (argc)
return KDB_ARGCOUNT;
kdb_printf("sysname %s\n", init_uts_ns.name.sysname);
kdb_printf("release %s\n", init_uts_ns.name.release);
kdb_printf("version %s\n", init_uts_ns.name.version);
kdb_printf("machine %s\n", init_uts_ns.name.machine);
kdb_printf("nodename %s\n", init_uts_ns.name.nodename);
kdb_printf("domainname %s\n", init_uts_ns.name.domainname);
kdb_printf("ccversion %s\n", __stringify(CCVERSION));
now = __ktime_get_real_seconds();
time64_to_tm(now, 0, &tm);
kdb_printf("date %04ld-%02d-%02d %02d:%02d:%02d "
"tz_minuteswest %d\n",
1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
sys_tz.tz_minuteswest);
kdb_sysinfo(&val);
kdb_printf("uptime ");
if (val.uptime > (24*60*60)) {
int days = val.uptime / (24*60*60);
val.uptime %= (24*60*60);
kdb_printf("%d day%s ", days, days == 1 ? "" : "s");
}
kdb_printf("%02ld:%02ld\n", val.uptime/(60*60), (val.uptime/60)%60);
kdb_printf("load avg %ld.%02ld %ld.%02ld %ld.%02ld\n",
LOAD_INT(val.loads[0]), LOAD_FRAC(val.loads[0]),
LOAD_INT(val.loads[1]), LOAD_FRAC(val.loads[1]),
LOAD_INT(val.loads[2]), LOAD_FRAC(val.loads[2]));
/* Display in kilobytes */
#define K(x) ((x) << (PAGE_SHIFT - 10))
kdb_printf("\nMemTotal: %8lu kB\nMemFree: %8lu kB\n"
"Buffers: %8lu kB\n",
K(val.totalram), K(val.freeram), K(val.bufferram));
return 0;
}
/*
* kdb_per_cpu - This function implements the 'per_cpu' command.
*/
static int kdb_per_cpu(int argc, const char **argv)
{
char fmtstr[64];
int cpu, diag, nextarg = 1;
unsigned long addr, symaddr, val, bytesperword = 0, whichcpu = ~0UL;
if (argc < 1 || argc > 3)
return KDB_ARGCOUNT;
diag = kdbgetaddrarg(argc, argv, &nextarg, &symaddr, NULL, NULL);
if (diag)
return diag;
if (argc >= 2) {
diag = kdbgetularg(argv[2], &bytesperword);
if (diag)
return diag;
}
if (!bytesperword)
bytesperword = KDB_WORD_SIZE;
else if (bytesperword > KDB_WORD_SIZE)
return KDB_BADWIDTH;
sprintf(fmtstr, "%%0%dlx ", (int)(2*bytesperword));
if (argc >= 3) {
diag = kdbgetularg(argv[3], &whichcpu);
if (diag)
return diag;
if (whichcpu >= nr_cpu_ids || !cpu_online(whichcpu)) {
kdb_printf("cpu %ld is not online\n", whichcpu);
return KDB_BADCPUNUM;
}
}
/* Most architectures use __per_cpu_offset[cpu], some use
* __per_cpu_offset(cpu), smp has no __per_cpu_offset.
*/
#ifdef __per_cpu_offset
#define KDB_PCU(cpu) __per_cpu_offset(cpu)
#else
#ifdef CONFIG_SMP
#define KDB_PCU(cpu) __per_cpu_offset[cpu]
#else
#define KDB_PCU(cpu) 0
#endif
#endif
for_each_online_cpu(cpu) {
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
if (whichcpu != ~0UL && whichcpu != cpu)
continue;
addr = symaddr + KDB_PCU(cpu);
diag = kdb_getword(&val, addr, bytesperword);
if (diag) {
kdb_printf("%5d " kdb_bfd_vma_fmt0 " - unable to "
"read, diag=%d\n", cpu, addr, diag);
continue;
}
kdb_printf("%5d ", cpu);
kdb_md_line(fmtstr, addr,
bytesperword == KDB_WORD_SIZE,
1, bytesperword, 1, 1, 0);
}
#undef KDB_PCU
return 0;
}
/*
* display help for the use of cmd | grep pattern
*/
static int kdb_grep_help(int argc, const char **argv)
{
kdb_printf("Usage of cmd args | grep pattern:\n");
kdb_printf(" Any command's output may be filtered through an ");
kdb_printf("emulated 'pipe'.\n");
kdb_printf(" 'grep' is just a key word.\n");
kdb_printf(" The pattern may include a very limited set of "
"metacharacters:\n");
kdb_printf(" pattern or ^pattern or pattern$ or ^pattern$\n");
kdb_printf(" And if there are spaces in the pattern, you may "
"quote it:\n");
kdb_printf(" \"pat tern\" or \"^pat tern\" or \"pat tern$\""
" or \"^pat tern$\"\n");
return 0;
}
/*
* kdb_register_flags - This function is used to register a kernel
* debugger command.
* Inputs:
* cmd Command name
* func Function to execute the command
* usage A simple usage string showing arguments
* help A simple help string describing command
* repeat Does the command auto repeat on enter?
* Returns:
* zero for success, one if a duplicate command.
*/
#define kdb_command_extend 50 /* arbitrary */
int kdb_register_flags(char *cmd,
kdb_func_t func,
char *usage,
char *help,
short minlen,
kdb_cmdflags_t flags)
{
int i;
kdbtab_t *kp;
/*
* Brute force method to determine duplicates
*/
for_each_kdbcmd(kp, i) {
if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
kdb_printf("Duplicate kdb command registered: "
"%s, func %px help %s\n", cmd, func, help);
return 1;
}
}
/*
* Insert command into first available location in table
*/
for_each_kdbcmd(kp, i) {
if (kp->cmd_name == NULL)
break;
}
if (i >= kdb_max_commands) {
kdbtab_t *new = kmalloc_array(kdb_max_commands -
KDB_BASE_CMD_MAX +
kdb_command_extend,
sizeof(*new),
GFP_KDB);
if (!new) {
kdb_printf("Could not allocate new kdb_command "
"table\n");
return 1;
}
if (kdb_commands) {
memcpy(new, kdb_commands,
(kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));
kfree(kdb_commands);
}
memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0,
kdb_command_extend * sizeof(*new));
kdb_commands = new;
kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;
kdb_max_commands += kdb_command_extend;
}
kp->cmd_name = cmd;
kp->cmd_func = func;
kp->cmd_usage = usage;
kp->cmd_help = help;
kp->cmd_minlen = minlen;
kp->cmd_flags = flags;
return 0;
}
EXPORT_SYMBOL_GPL(kdb_register_flags);
/*
* kdb_register - Compatibility register function for commands that do
* not need to specify a repeat state. Equivalent to
* kdb_register_flags with flags set to 0.
* Inputs:
* cmd Command name
* func Function to execute the command
* usage A simple usage string showing arguments
* help A simple help string describing command
* Returns:
* zero for success, one if a duplicate command.
*/
int kdb_register(char *cmd,
kdb_func_t func,
char *usage,
char *help,
short minlen)
{
return kdb_register_flags(cmd, func, usage, help, minlen, 0);
}
EXPORT_SYMBOL_GPL(kdb_register);
/*
* kdb_unregister - This function is used to unregister a kernel
* debugger command. It is generally called when a module which
* implements kdb commands is unloaded.
* Inputs:
* cmd Command name
* Returns:
* zero for success, one command not registered.
*/
int kdb_unregister(char *cmd)
{
int i;
kdbtab_t *kp;
/*
* find the command.
*/
for_each_kdbcmd(kp, i) {
if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
kp->cmd_name = NULL;
return 0;
}
}
/* Couldn't find it. */
return 1;
}
EXPORT_SYMBOL_GPL(kdb_unregister);
/* Initialize the kdb command table. */
static void __init kdb_inittab(void)
{
int i;
kdbtab_t *kp;
for_each_kdbcmd(kp, i)
kp->cmd_name = NULL;
kdb_register_flags("md", kdb_md, "<vaddr>",
"Display Memory Contents, also mdWcN, e.g. md8c1", 1,
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
kdb_register_flags("mdr", kdb_md, "<vaddr> <bytes>",
"Display Raw Memory", 0,
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
kdb_register_flags("mdp", kdb_md, "<paddr> <bytes>",
"Display Physical Memory", 0,
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
kdb_register_flags("mds", kdb_md, "<vaddr>",
"Display Memory Symbolically", 0,
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
kdb_register_flags("mm", kdb_mm, "<vaddr> <contents>",
"Modify Memory Contents", 0,
KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS);
kdb_register_flags("go", kdb_go, "[<vaddr>]",
"Continue Execution", 1,
KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
kdb_register_flags("rd", kdb_rd, "",
"Display Registers", 0,
KDB_ENABLE_REG_READ);
kdb_register_flags("rm", kdb_rm, "<reg> <contents>",
"Modify Registers", 0,
KDB_ENABLE_REG_WRITE);
kdb_register_flags("ef", kdb_ef, "<vaddr>",
"Display exception frame", 0,
KDB_ENABLE_MEM_READ);
kdb_register_flags("bt", kdb_bt, "[<vaddr>]",
"Stack traceback", 1,
KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
kdb_register_flags("btp", kdb_bt, "<pid>",
"Display stack for process <pid>", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
"Backtrace all processes matching state flag", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("btc", kdb_bt, "",
"Backtrace current process on each cpu", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("btt", kdb_bt, "<vaddr>",
"Backtrace process given its struct task address", 0,
KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
kdb_register_flags("env", kdb_env, "",
"Show environment variables", 0,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("set", kdb_set, "",
"Set environment variables", 0,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("help", kdb_help, "",
"Display Help Message", 1,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("?", kdb_help, "",
"Display Help Message", 0,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("cpu", kdb_cpu, "<cpunum>",
"Switch to new cpu", 0,
KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
kdb_register_flags("kgdb", kdb_kgdb, "",
"Enter kgdb mode", 0, 0);
kdb_register_flags("ps", kdb_ps, "[<flags>|A]",
"Display active task list", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("pid", kdb_pid, "<pidnum>",
"Switch to another task", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("reboot", kdb_reboot, "",
"Reboot the machine immediately", 0,
KDB_ENABLE_REBOOT);
#if defined(CONFIG_MODULES)
kdb_register_flags("lsmod", kdb_lsmod, "",
"List loaded kernel modules", 0,
KDB_ENABLE_INSPECT);
#endif
#if defined(CONFIG_MAGIC_SYSRQ)
kdb_register_flags("sr", kdb_sr, "<key>",
"Magic SysRq key", 0,
KDB_ENABLE_ALWAYS_SAFE);
#endif
#if defined(CONFIG_PRINTK)
kdb_register_flags("dmesg", kdb_dmesg, "[lines]",
"Display syslog buffer", 0,
KDB_ENABLE_ALWAYS_SAFE);
#endif
if (arch_kgdb_ops.enable_nmi) {
kdb_register_flags("disable_nmi", kdb_disable_nmi, "",
"Disable NMI entry to KDB", 0,
KDB_ENABLE_ALWAYS_SAFE);
}
kdb_register_flags("defcmd", kdb_defcmd, "name \"usage\" \"help\"",
"Define a set of commands, down to endefcmd", 0,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("kill", kdb_kill, "<-signal> <pid>",
"Send a signal to a process", 0,
KDB_ENABLE_SIGNAL);
kdb_register_flags("summary", kdb_summary, "",
"Summarize the system", 4,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]",
"Display per_cpu variables", 3,
KDB_ENABLE_MEM_READ);
kdb_register_flags("grephelp", kdb_grep_help, "",
"Display help on | grep", 0,
KDB_ENABLE_ALWAYS_SAFE);
}
/* Execute any commands defined in kdb_cmds. */
static void __init kdb_cmd_init(void)
{
int i, diag;
for (i = 0; kdb_cmds[i]; ++i) {
diag = kdb_parse(kdb_cmds[i]);
if (diag)
kdb_printf("kdb command %s failed, kdb diag %d\n",
kdb_cmds[i], diag);
}
if (defcmd_in_progress) {
kdb_printf("Incomplete 'defcmd' set, forcing endefcmd\n");
kdb_parse("endefcmd");
}
}
/* Initialize kdb_printf, breakpoint tables and kdb state */
void __init kdb_init(int lvl)
{
static int kdb_init_lvl = KDB_NOT_INITIALIZED;
int i;
if (kdb_init_lvl == KDB_INIT_FULL || lvl <= kdb_init_lvl)
return;
for (i = kdb_init_lvl; i < lvl; i++) {
switch (i) {
case KDB_NOT_INITIALIZED:
kdb_inittab(); /* Initialize Command Table */
kdb_initbptab(); /* Initialize Breakpoints */
break;
case KDB_INIT_EARLY:
kdb_cmd_init(); /* Build kdb_cmds tables */
break;
}
}
kdb_init_lvl = lvl;
}