···400400nowayout: Watchdog cannot be stopped once started401401 (default=kernel config parameter)402402-------------------------------------------------403403+sun4v_wdt:404404+timeout_ms: Watchdog timeout in milliseconds 1..180000, default=60000)405405+nowayout: Watchdog cannot be stopped once started406406+-------------------------------------------------
···2424export BITS := 322525UTS_MACHINE := sparc26262727+# We are adding -Wa,-Av8 to KBUILD_CFLAGS to deal with a specs bug in some2828+# versions of gcc. Some gcc versions won't pass -Av8 to binutils when you2929+# give -mcpu=v8. This silently worked with older bintutils versions but3030+# does not any more.2731KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g73232+KBUILD_CFLAGS += -Wa,-Av83333+2834KBUILD_AFLAGS += -m32 -Wa,-Av829353036else
+2-1
arch/sparc/include/uapi/asm/unistd.h
···422422#define __NR_listen 354423423#define __NR_setsockopt 355424424#define __NR_mlock2 356425425+#define __NR_copy_file_range 357425426426426-#define NR_syscalls 357427427+#define NR_syscalls 358427428428429/* Bitmask values returned from kern_features system call. */429430#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001
···5252 unsigned char fenab;5353 int err;54545555- flush_user_windows();5555+ synchronize_user_stack();5656 if (get_thread_wsaved() ||5757 (((unsigned long)ucp) & (sizeof(unsigned long)-1)) ||5858 (!__access_ok(ucp, sizeof(*ucp))))
+1
arch/sparc/kernel/sparc_ksyms_64.c
···3737EXPORT_SYMBOL(sun4v_niagara_setperf);3838EXPORT_SYMBOL(sun4v_niagara2_getperf);3939EXPORT_SYMBOL(sun4v_niagara2_setperf);4040+EXPORT_SYMBOL(sun4v_mach_set_watchdog);40414142/* from hweight.S */4243EXPORT_SYMBOL(__arch_hweight8);
···9292 CT_UNALIGNED_LOAD_STORE_WRITE,9393 CT_OVERWRITE_ALLOCATION,9494 CT_WRITE_AFTER_FREE,9595+ CT_READ_AFTER_FREE,9696+ CT_WRITE_BUDDY_AFTER_FREE,9797+ CT_READ_BUDDY_AFTER_FREE,9598 CT_SOFTLOCKUP,9699 CT_HARDLOCKUP,97100 CT_SPINLOCKUP,···107104 CT_ACCESS_USERSPACE,108105 CT_WRITE_RO,109106 CT_WRITE_KERN,107107+ CT_WRAP_ATOMIC110108};111109112110static char* cp_name[] = {···133129 "UNALIGNED_LOAD_STORE_WRITE",134130 "OVERWRITE_ALLOCATION",135131 "WRITE_AFTER_FREE",132132+ "READ_AFTER_FREE",133133+ "WRITE_BUDDY_AFTER_FREE",134134+ "READ_BUDDY_AFTER_FREE",136135 "SOFTLOCKUP",137136 "HARDLOCKUP",138137 "SPINLOCKUP",···148141 "ACCESS_USERSPACE",149142 "WRITE_RO",150143 "WRITE_KERN",144144+ "WRAP_ATOMIC"151145};152146153147static struct jprobe lkdtm;···417409 break;418410 }419411 case CT_WRITE_AFTER_FREE: {412412+ int *base, *again;420413 size_t len = 1024;421421- u32 *data = kmalloc(len, GFP_KERNEL);414414+ /*415415+ * The slub allocator uses the first word to store the free416416+ * pointer in some configurations. Use the middle of the417417+ * allocation to avoid running into the freelist418418+ */419419+ size_t offset = (len / sizeof(*base)) / 2;422420423423- kfree(data);421421+ base = kmalloc(len, GFP_KERNEL);422422+ pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]);423423+ pr_info("Attempting bad write to freed memory at %p\n",424424+ &base[offset]);425425+ kfree(base);426426+ base[offset] = 0x0abcdef0;427427+ /* Attempt to notice the overwrite. */428428+ again = kmalloc(len, GFP_KERNEL);429429+ kfree(again);430430+ if (again != base)431431+ pr_info("Hmm, didn't get the same memory range.\n");432432+433433+ break;434434+ }435435+ case CT_READ_AFTER_FREE: {436436+ int *base, *val, saw;437437+ size_t len = 1024;438438+ /*439439+ * The slub allocator uses the first word to store the free440440+ * pointer in some configurations. Use the middle of the441441+ * allocation to avoid running into the freelist442442+ */443443+ size_t offset = (len / sizeof(*base)) / 2;444444+445445+ base = kmalloc(len, GFP_KERNEL);446446+ if (!base)447447+ break;448448+449449+ val = kmalloc(len, GFP_KERNEL);450450+ if (!val)451451+ break;452452+453453+ *val = 0x12345678;454454+ base[offset] = *val;455455+ pr_info("Value in memory before free: %x\n", base[offset]);456456+457457+ kfree(base);458458+459459+ pr_info("Attempting bad read from freed memory\n");460460+ saw = base[offset];461461+ if (saw != *val) {462462+ /* Good! Poisoning happened, so declare a win. */463463+ pr_info("Memory correctly poisoned (%x)\n", saw);464464+ BUG();465465+ }466466+ pr_info("Memory was not poisoned\n");467467+468468+ kfree(val);469469+ break;470470+ }471471+ case CT_WRITE_BUDDY_AFTER_FREE: {472472+ unsigned long p = __get_free_page(GFP_KERNEL);473473+ if (!p)474474+ break;475475+ pr_info("Writing to the buddy page before free\n");476476+ memset((void *)p, 0x3, PAGE_SIZE);477477+ free_page(p);424478 schedule();425425- memset(data, 0x78, len);479479+ pr_info("Attempting bad write to the buddy page after free\n");480480+ memset((void *)p, 0x78, PAGE_SIZE);481481+ /* Attempt to notice the overwrite. */482482+ p = __get_free_page(GFP_KERNEL);483483+ free_page(p);484484+ schedule();485485+486486+ break;487487+ }488488+ case CT_READ_BUDDY_AFTER_FREE: {489489+ unsigned long p = __get_free_page(GFP_KERNEL);490490+ int saw, *val = kmalloc(1024, GFP_KERNEL);491491+ int *base;492492+493493+ if (!p)494494+ break;495495+496496+ if (!val)497497+ break;498498+499499+ base = (int *)p;500500+501501+ *val = 0x12345678;502502+ base[0] = *val;503503+ pr_info("Value in memory before free: %x\n", base[0]);504504+ free_page(p);505505+ pr_info("Attempting to read from freed memory\n");506506+ saw = base[0];507507+ if (saw != *val) {508508+ /* Good! Poisoning happened, so declare a win. */509509+ pr_info("Memory correctly poisoned (%x)\n", saw);510510+ BUG();511511+ }512512+ pr_info("Buddy page was not poisoned\n");513513+514514+ kfree(val);426515 break;427516 }428517 case CT_SOFTLOCKUP:···632527633528 do_overwritten();634529 break;530530+ }531531+ case CT_WRAP_ATOMIC: {532532+ atomic_t under = ATOMIC_INIT(INT_MIN);533533+ atomic_t over = ATOMIC_INIT(INT_MAX);534534+535535+ pr_info("attempting atomic underflow\n");536536+ atomic_dec(&under);537537+ pr_info("attempting atomic overflow\n");538538+ atomic_inc(&over);539539+540540+ return;635541 }636542 case CT_NONE:637543 default:
+11
drivers/watchdog/Kconfig
···15841584 machines. The watchdog timeout period is normally one minute but15851585 can be changed with a boot-time parameter.1586158615871587+config WATCHDOG_SUN4V15881588+ tristate "Sun4v Watchdog support"15891589+ select WATCHDOG_CORE15901590+ depends on SPARC6415911591+ help15921592+ Say Y here to support the hypervisor watchdog capability embedded15931593+ in the SPARC sun4v architecture.15941594+15951595+ To compile this driver as a module, choose M here. The module will15961596+ be called sun4v_wdt.15971597+15871598# XTENSA Architecture1588159915891600# Xen Architecture
···11+/*22+ * sun4v watchdog timer33+ * (c) Copyright 2016 Oracle Corporation44+ *55+ * Implement a simple watchdog driver using the built-in sun4v hypervisor66+ * watchdog support. If time expires, the hypervisor stops or bounces77+ * the guest domain.88+ *99+ * This program is free software; you can redistribute it and/or1010+ * modify it under the terms of the GNU General Public License1111+ * as published by the Free Software Foundation; either version1212+ * 2 of the License, or (at your option) any later version.1313+ */1414+1515+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt1616+1717+#include <linux/errno.h>1818+#include <linux/init.h>1919+#include <linux/kernel.h>2020+#include <linux/module.h>2121+#include <linux/moduleparam.h>2222+#include <linux/watchdog.h>2323+#include <asm/hypervisor.h>2424+#include <asm/mdesc.h>2525+2626+#define WDT_TIMEOUT 602727+#define WDT_MAX_TIMEOUT 315360002828+#define WDT_MIN_TIMEOUT 12929+#define WDT_DEFAULT_RESOLUTION_MS 1000 /* 1 second */3030+3131+static unsigned int timeout;3232+module_param(timeout, uint, 0);3333+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="3434+ __MODULE_STRING(WDT_TIMEOUT) ")");3535+3636+static bool nowayout = WATCHDOG_NOWAYOUT;3737+module_param(nowayout, bool, S_IRUGO);3838+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="3939+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");4040+4141+static int sun4v_wdt_stop(struct watchdog_device *wdd)4242+{4343+ sun4v_mach_set_watchdog(0, NULL);4444+4545+ return 0;4646+}4747+4848+static int sun4v_wdt_ping(struct watchdog_device *wdd)4949+{5050+ int hverr;5151+5252+ /*5353+ * HV watchdog timer will round up the timeout5454+ * passed in to the nearest multiple of the5555+ * watchdog resolution in milliseconds.5656+ */5757+ hverr = sun4v_mach_set_watchdog(wdd->timeout * 1000, NULL);5858+ if (hverr == HV_EINVAL)5959+ return -EINVAL;6060+6161+ return 0;6262+}6363+6464+static int sun4v_wdt_set_timeout(struct watchdog_device *wdd,6565+ unsigned int timeout)6666+{6767+ wdd->timeout = timeout;6868+6969+ return 0;7070+}7171+7272+static const struct watchdog_info sun4v_wdt_ident = {7373+ .options = WDIOF_SETTIMEOUT |7474+ WDIOF_MAGICCLOSE |7575+ WDIOF_KEEPALIVEPING,7676+ .identity = "sun4v hypervisor watchdog",7777+ .firmware_version = 0,7878+};7979+8080+static struct watchdog_ops sun4v_wdt_ops = {8181+ .owner = THIS_MODULE,8282+ .start = sun4v_wdt_ping,8383+ .stop = sun4v_wdt_stop,8484+ .ping = sun4v_wdt_ping,8585+ .set_timeout = sun4v_wdt_set_timeout,8686+};8787+8888+static struct watchdog_device wdd = {8989+ .info = &sun4v_wdt_ident,9090+ .ops = &sun4v_wdt_ops,9191+ .min_timeout = WDT_MIN_TIMEOUT,9292+ .max_timeout = WDT_MAX_TIMEOUT,9393+ .timeout = WDT_TIMEOUT,9494+};9595+9696+static int __init sun4v_wdt_init(void)9797+{9898+ struct mdesc_handle *handle;9999+ u64 node;100100+ const u64 *value;101101+ int err = 0;102102+ unsigned long major = 1, minor = 1;103103+104104+ /*105105+ * There are 2 properties that can be set from the control106106+ * domain for the watchdog.107107+ * watchdog-resolution108108+ * watchdog-max-timeout109109+ *110110+ * We can expect a handle to be returned otherwise something111111+ * serious is wrong. Correct to return -ENODEV here.112112+ */113113+114114+ handle = mdesc_grab();115115+ if (!handle)116116+ return -ENODEV;117117+118118+ node = mdesc_node_by_name(handle, MDESC_NODE_NULL, "platform");119119+ err = -ENODEV;120120+ if (node == MDESC_NODE_NULL)121121+ goto out_release;122122+123123+ /*124124+ * This is a safe way to validate if we are on the right125125+ * platform.126126+ */127127+ if (sun4v_hvapi_register(HV_GRP_CORE, major, &minor))128128+ goto out_hv_unreg;129129+130130+ /* Allow value of watchdog-resolution up to 1s (default) */131131+ value = mdesc_get_property(handle, node, "watchdog-resolution", NULL);132132+ err = -EINVAL;133133+ if (value) {134134+ if (*value == 0 ||135135+ *value > WDT_DEFAULT_RESOLUTION_MS)136136+ goto out_hv_unreg;137137+ }138138+139139+ value = mdesc_get_property(handle, node, "watchdog-max-timeout", NULL);140140+ if (value) {141141+ /*142142+ * If the property value (in ms) is smaller than143143+ * min_timeout, return -EINVAL.144144+ */145145+ if (*value < wdd.min_timeout * 1000)146146+ goto out_hv_unreg;147147+148148+ /*149149+ * If the property value is smaller than150150+ * default max_timeout then set watchdog max_timeout to151151+ * the value of the property in seconds.152152+ */153153+ if (*value < wdd.max_timeout * 1000)154154+ wdd.max_timeout = *value / 1000;155155+ }156156+157157+ watchdog_init_timeout(&wdd, timeout, NULL);158158+159159+ watchdog_set_nowayout(&wdd, nowayout);160160+161161+ err = watchdog_register_device(&wdd);162162+ if (err)163163+ goto out_hv_unreg;164164+165165+ pr_info("initialized (timeout=%ds, nowayout=%d)\n",166166+ wdd.timeout, nowayout);167167+168168+ mdesc_release(handle);169169+170170+ return 0;171171+172172+out_hv_unreg:173173+ sun4v_hvapi_unregister(HV_GRP_CORE);174174+175175+out_release:176176+ mdesc_release(handle);177177+ return err;178178+}179179+180180+static void __exit sun4v_wdt_exit(void)181181+{182182+ sun4v_hvapi_unregister(HV_GRP_CORE);183183+ watchdog_unregister_device(&wdd);184184+}185185+186186+module_init(sun4v_wdt_init);187187+module_exit(sun4v_wdt_exit);188188+189189+MODULE_AUTHOR("Wim Coekaerts <wim.coekaerts@oracle.com>");190190+MODULE_DESCRIPTION("sun4v watchdog driver");191191+MODULE_LICENSE("GPL");