diff -Nru skiboot-6.5.2/debian/changelog skiboot-6.5.2/debian/changelog --- skiboot-6.5.2/debian/changelog 2020-01-15 07:56:04.000000000 -0600 +++ skiboot-6.5.2/debian/changelog 2020-12-07 16:03:03.000000000 -0600 @@ -1,3 +1,14 @@ +skiboot (6.5.2-1ubuntu0.20.10.1) groovy; urgency=medium + + * opal-prd: mmap(range:ibm,hbrt-code-image,...) fails with EPERM + (LP: #1905393) opal-prd fails to start + d/patches/0005-fix-opal-prd-fail-with-EPERM.patch + * opal-prd: Have a worker process handle page offlining + (LP: #1904585) Have a worker process handle page offlining + d/patches/0006-fix-opal-prd-have-worker-process-handle-page-offlining.patch + + -- Matthieu Clemenceau Mon, 07 Dec 2020 16:03:03 -0600 + skiboot (6.5.2-1) unstable; urgency=medium * Update to new upstream version 6.5.2. diff -Nru skiboot-6.5.2/debian/control skiboot-6.5.2/debian/control --- skiboot-6.5.2/debian/control 2020-01-15 07:56:04.000000000 -0600 +++ skiboot-6.5.2/debian/control 2020-12-07 16:03:03.000000000 -0600 @@ -1,7 +1,8 @@ Source: skiboot Section: admin Priority: optional -Maintainer: Frédéric Bonnard +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Frédéric Bonnard Build-Depends: debhelper-compat (= 12) Standards-Version: 4.4.1 Rules-Requires-Root: no diff -Nru skiboot-6.5.2/debian/patches/0005-fix-opal-prd-fail-with-EPERM.patch skiboot-6.5.2/debian/patches/0005-fix-opal-prd-fail-with-EPERM.patch --- skiboot-6.5.2/debian/patches/0005-fix-opal-prd-fail-with-EPERM.patch 1969-12-31 18:00:00.000000000 -0600 +++ skiboot-6.5.2/debian/patches/0005-fix-opal-prd-fail-with-EPERM.patch 2020-12-07 16:03:03.000000000 -0600 @@ -0,0 +1,60 @@ +--- a/external/opal-prd/opal-prd.c ++++ b/external/opal-prd/opal-prd.c +@@ -947,7 +947,9 @@ + static int map_hbrt_physmem(struct opal_prd_ctx *ctx, const char *name) + { + struct prd_range *range; ++ int rc; + void *buf; ++ void *ro_buf; + + range = find_range(name, 0); + if (!range) { +@@ -955,15 +957,45 @@ + return -1; + } + +- buf = mmap(NULL, range->size, PROT_READ | PROT_WRITE | PROT_EXEC, ++ ro_buf = mmap(NULL, range->size, PROT_READ, + MAP_PRIVATE, ctx->fd, range->physaddr); +- if (buf == MAP_FAILED) { ++ if (ro_buf == MAP_FAILED) { + pr_log(LOG_ERR, "IMAGE: mmap(range:%s, " + "phys:0x%016lx, size:0x%016lx) failed: %m", + name, range->physaddr, range->size); + return -1; + } + ++ buf = mmap(NULL, range->size, PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_ANONYMOUS, -1 , 0); ++ if (buf == MAP_FAILED) { ++ pr_log(LOG_ERR, "IMAGE: anon mmap(size:0x%016lx) failed: %m", ++ range->size); ++ return -1; ++ } ++ ++ memcpy(buf, ro_buf, range->size); ++ ++ rc = munmap(ro_buf, range->size); ++ if (rc < 0) { ++ pr_log(LOG_ERR, "IMAGE: munmap(" ++ "phys:0x%016lx, size:0x%016lx) failed: %m", ++ range->physaddr, range->size); ++ return -1; ++ } ++ ++ /* ++ * FIXME: We shouldn't be mapping the memory as RWX, but HBRT appears to ++ * require the ability to write into the image at runtime. ++ */ ++ rc = mprotect(buf, range->size, PROT_READ | PROT_WRITE | PROT_EXEC); ++ if (rc < 0) { ++ pr_log(LOG_ERR, "IMAGE: mprotect(phys:%p, " ++ "size:0x%016lx, rwx) failed: %m", ++ buf, range->size); ++ return -1; ++ } ++ + ctx->code_addr = buf; + ctx->code_size = range->size; + return 0; diff -Nru skiboot-6.5.2/debian/patches/0006-fix-opal-prd-have-worker-process-handle-page-offlining.patch skiboot-6.5.2/debian/patches/0006-fix-opal-prd-have-worker-process-handle-page-offlining.patch --- skiboot-6.5.2/debian/patches/0006-fix-opal-prd-have-worker-process-handle-page-offlining.patch 1969-12-31 18:00:00.000000000 -0600 +++ skiboot-6.5.2/debian/patches/0006-fix-opal-prd-have-worker-process-handle-page-offlining.patch 2020-12-07 16:03:03.000000000 -0600 @@ -0,0 +1,128 @@ +--- a/external/opal-prd/opal-prd.c ++++ b/external/opal-prd/opal-prd.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -695,13 +696,42 @@ + return rc; + } + ++static int memory_error_worker(const char *sysfsfile, const char *type, ++ uint64_t i_start_addr, uint64_t i_endAddr) ++{ ++ int memfd, rc, n, ret = 0; ++ char buf[ADDR_STRING_SZ]; ++ uint64_t addr; ++ ++ memfd = open(sysfsfile, O_WRONLY); ++ if (memfd < 0) { ++ pr_log(LOG_CRIT, "MEM: Failed to offline memory! " ++ "Unable to open sysfs node %s: %m", sysfsfile); ++ return -1; ++ } ++ ++ for (addr = i_start_addr; addr <= i_endAddr; addr += ctx->page_size) { ++ n = snprintf(buf, ADDR_STRING_SZ, "0x%lx", addr); ++ rc = write(memfd, buf, n); ++ if (rc != n) { ++ pr_log(LOG_CRIT, "MEM: Failed to offline memory! " ++ "page addr: %016lx type: %s: %m", ++ addr, type); ++ ret = 1; ++ } ++ } ++ pr_log(LOG_CRIT, "MEM: Offlined %016lx,%016lx, type %s: %m\n", ++ i_start_addr, addr, type); ++ ++ close(memfd); ++ return ret; ++} ++ + int hservice_memory_error(uint64_t i_start_addr, uint64_t i_endAddr, + enum MemoryError_t i_errorType) + { + const char *sysfsfile, *typestr; +- char buf[ADDR_STRING_SZ]; +- int memfd, rc, n, ret = 0; +- uint64_t addr; ++ pid_t pid; + + switch(i_errorType) { + case MEMORY_ERROR_CE: +@@ -721,26 +751,21 @@ + pr_log(LOG_ERR, "MEM: Memory error: range %016lx-%016lx, type: %s", + i_start_addr, i_endAddr, typestr); + ++ /* ++ * HBRT expects the memory offlining process to happen in the background ++ * after the notification is delivered. ++ */ ++ pid = fork(); ++ if (pid > 0) ++ exit(memory_error_worker(sysfsfile, typestr, i_start_addr, i_endAddr)); + +- memfd = open(sysfsfile, O_WRONLY); +- if (memfd < 0) { +- pr_log(LOG_CRIT, "MEM: Failed to offline memory! " +- "Unable to open sysfs node %s: %m", sysfsfile); ++ if (pid < 0) { ++ perror("MEM: unable to fork worker to offline memory!\n"); + return -1; + } + +- for (addr = i_start_addr; addr <= i_endAddr; addr += ctx->page_size) { +- n = snprintf(buf, ADDR_STRING_SZ, "0x%lx", addr); +- rc = write(memfd, buf, n); +- if (rc != n) { +- pr_log(LOG_CRIT, "MEM: Failed to offline memory! " +- "page addr: %016lx type: %d: %m", +- addr, i_errorType); +- ret = rc; +- } +- } +- +- return ret; ++ pr_log(LOG_INFO, "MEM: forked off %d to handle mem error\n", pid); ++ return 0; + } + + uint64_t hservice_get_interface_capabilities(uint64_t set) +@@ -2143,6 +2168,10 @@ + return 0; + } + ++static struct sigaction sigchild_action = { ++ .sa_flags = SA_NOCLDWAIT | SA_RESTART, ++ .sa_handler = SIG_DFL, ++}; + + static int run_prd_daemon(struct opal_prd_ctx *ctx) + { +@@ -2270,6 +2299,22 @@ + pr_debug("SCOM: f00f: %lx", be64toh(val)); + } + ++ /* ++ * Setup the SIGCHLD handler to automatically reap the worker threads ++ * we use for memory offlining. We can't do this earlier since the ++ * modprobe helper spawns workers and wants to check their exit status ++ * with waitpid(). Auto-reaping breaks that so enable it just before ++ * entering the attn loop. ++ * ++ * We also setup system call restarting on SIGCHLD since opal-prd ++ * doesn't make any real attempt to handle blocking functions exiting ++ * due to EINTR. ++ */ ++ if (sigaction(SIGCHLD, &sigchild_action, NULL)) { ++ pr_log(LOG_ERR, "CTRL: Failed to register signal handler %m\n"); ++ return -1; ++ } ++ + run_attn_loop(ctx); + rc = 0; + diff -Nru skiboot-6.5.2/debian/patches/series skiboot-6.5.2/debian/patches/series --- skiboot-6.5.2/debian/patches/series 2020-01-15 07:56:04.000000000 -0600 +++ skiboot-6.5.2/debian/patches/series 2020-12-07 16:03:03.000000000 -0600 @@ -2,3 +2,5 @@ 0002-Use-default-m32-m64-gcc-flag.patch 0003-Use-file-operation-used-on-x86-for-ARCH_UNKNOWN.patch 0004-Move-sbin-commands-manpages-from-section-1-to-8.patch +0005-fix-opal-prd-fail-with-EPERM.patch +0006-fix-opal-prd-have-worker-process-handle-page-offlining.patch