All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
To: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Cc: <igt-dev@lists.freedesktop.org>
Subject: Re: [PATCH i-g-t 1/2] lib/igt_pm: Add helpers for hibernating kernel
Date: Thu, 5 Dec 2024 16:49:58 -0500	[thread overview]
Message-ID: <Z1IgBqtKWdkMycN-@intel.com> (raw)
In-Reply-To: <20241203092418.3454357-2-juhapekka.heikkila@gmail.com>

On Tue, Dec 03, 2024 at 11:24:17AM +0200, Juha-Pekka Heikkila wrote:
> Here added
> 
> igt_pm_check_hibernation_support()
> igt_pm_ensure_grub_boots_same_kernel()
> 
> to check if kernel is configured for resuming from hibernation
> and helper to set grub booting currently run kernel on next reboot.
> 
> Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
> ---
>  lib/igt_pm.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/igt_pm.h |   2 +
>  2 files changed, 157 insertions(+)
> 
> diff --git a/lib/igt_pm.c b/lib/igt_pm.c
> index 1a5d9c42b..2055996bc 100644
> --- a/lib/igt_pm.c
> +++ b/lib/igt_pm.c
> @@ -1470,3 +1470,158 @@ void igt_pm_ignore_slpc_efficient_freq(int i915, int gtfd, bool val)
>  	igt_require(igt_sysfs_has_attr(gtfd, "slpc_ignore_eff_freq"));
>  	igt_sysfs_set_u32(gtfd, "slpc_ignore_eff_freq", val);
>  }
> +
> +/**
> + * igt_pm_check_hibernation_support:
> + *
> + * Return: True if kernel is configured with resume point for hibernate.
> + */
> +bool igt_pm_check_hibernation_support(void)
> +{
> +	int fd;
> +	char buffer[2048];
> +	ssize_t bytes_read;
> +	FILE *cmdline;
> +
> +	/* Check if hibernation is supported in /sys/power/state */
> +	fd = open("/sys/power/state", O_RDONLY);
> +
> +	if (fd <= 0) {
> +		igt_debug("Failed to open /sys/power/state\n");
> +		return false;
> +	}
> +
> +	bytes_read = read(fd, buffer, sizeof(buffer) - 1);
> +	close(fd);
> +
> +	if (bytes_read <= 0) {
> +		igt_debug("Failed to read /sys/power/state");
> +		return false;
> +	}
> +
> +	buffer[bytes_read] = '\0';
> +	if (strstr(buffer, "disk") == NULL) {
> +		igt_debug("Hibernation (suspend to disk) is not supported on this system.\n");
> +		return false;
> +	}
> +
> +	/* Check if resume is configured in kernel command line */
> +	cmdline = fopen("/proc/cmdline", "r");
> +
> +	if (!cmdline) {
> +		igt_debug("Failed to open /proc/cmdline");
> +		return false;
> +	}
> +
> +	fread(buffer, 1, sizeof(buffer) - 1, cmdline);
> +	fclose(cmdline);
> +
> +	if (strstr(buffer, "resume=") == NULL) {
> +		igt_debug("Kernel does not have 'resume' parameter configured for hibernation.\n");
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +/**
> + * igt_pm_ensure_grub_boots_same_kernel:
> + *
> + * Return: True if kernel was found and set for next reboot.
> + */
> +bool igt_pm_ensure_grub_boots_same_kernel(void)
> +{
> +	char cmdline[1024];
> +	char current_kernel[256];
> +	char last_menuentry[512] = "";
> +	char grub_entry[512];
> +	char command[1024];
> +	FILE *cmdline_file, *grub_cfg;
> +	char line[1024];
> +	bool kernel_found = false;
> +	char *kernel_arg;
> +	char *kernel_end;
> +
> +	/* Read /proc/cmdline to get the current kernel image */
> +	cmdline_file = fopen("/proc/cmdline", "r");
> +	if (!cmdline_file) {
> +		igt_debug("Failed to open /proc/cmdline");
> +		return false;
> +	}
> +
> +	if (!fgets(cmdline, sizeof(cmdline), cmdline_file)) {
> +		fclose(cmdline_file);
> +		igt_debug("Failed to read /proc/cmdline");
> +		return false;
> +	}
> +	fclose(cmdline_file);
> +
> +	/* Parse the kernel image from cmdline */
> +	kernel_arg = strstr(cmdline, "BOOT_IMAGE=");
> +	if (!kernel_arg) {
> +		igt_debug("BOOT_IMAGE= not found in /proc/cmdline\n");
> +		return false;
> +	}
> +
> +	kernel_arg += strlen("BOOT_IMAGE=");
> +	kernel_end = strchr(kernel_arg, ' ');
> +
> +	if (!kernel_end)
> +		kernel_end = kernel_arg + strlen(kernel_arg);
> +
> +	snprintf(current_kernel, sizeof(current_kernel), "%.*s",
> +		 (int)(kernel_end - kernel_arg), kernel_arg);
> +	igt_debug("Current kernel image: %s\n", current_kernel);
> +
> +	/* Open GRUB config file to find matching entry */
> +	grub_cfg = fopen("/boot/grub/grub.cfg", "r");

The problem is that this depends on distro and with or without EFI...

in my Fedora here:

$ cat /boot/grub/grub.cfg
cat: /boot/grub/grub.cfg: No such file or directory


> +	if (!grub_cfg) {
> +		igt_debug("Failed to open GRUB configuration file");
> +		return false;
> +	}
> +
> +	while (fgets(line, sizeof(line), grub_cfg)) {
> +		/* Check if the line contains a menuentry */
> +		if (strstr(line, "menuentry")) {

Also I believe this can change from distro to distro...
It should be better to have a generic way using other tools that
could give us the default or next boot...

> +		/* Store the menuentry line */
> +			char *start = strchr(line, '\'');
> +			char *end = start ? strchr(start + 1, '\'') : NULL;
> +
> +			if (start && end) {
> +				snprintf(last_menuentry,
> +					 sizeof(last_menuentry),
> +					 "%.*s", (int)(end - start - 1),
> +					 start + 1);
> +			}
> +		}
> +
> +		/* Check if the current line contains the kernel */
> +		if (strstr(line, current_kernel)) {
> +			/* Use the last seen menuentry as the match */
> +			snprintf(grub_entry, sizeof(grub_entry), "%s",
> +				 last_menuentry);
> +			kernel_found = true;
> +			break;
> +		}
> +	}
> +
> +	fclose(grub_cfg);
> +
> +	if (!kernel_found) {
> +		igt_debug("Failed to find matching GRUB entry for kernel: %s\n",
> +			  current_kernel);
> +		return false;
> +	}
> +
> +	/* Set the GRUB boot target using grub-reboot */
> +	snprintf(command, sizeof(command), "grub-reboot \"%s\"", grub_entry);
> +	if (system(command) != 0) {
> +		igt_debug("Failed to set GRUB boot target to: %s\n",
> +			  grub_entry);
> +		return false;
> +	}
> +
> +	igt_debug("Set GRUB to boot kernel: %s (GRUB entry: %s)\n",
> +		  current_kernel, grub_entry);
> +	return true;
> +}
> diff --git a/lib/igt_pm.h b/lib/igt_pm.h
> index 6b428f53e..7cc774e85 100644
> --- a/lib/igt_pm.h
> +++ b/lib/igt_pm.h
> @@ -97,5 +97,7 @@ uint64_t igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev);
>  uint64_t igt_pm_get_runtime_active_time(struct pci_device *pci_dev);
>  int igt_pm_get_runtime_usage(struct pci_device *pci_dev);
>  void igt_pm_ignore_slpc_efficient_freq(int i915, int gtfd, bool val);
> +bool igt_pm_check_hibernation_support(void);
> +bool igt_pm_ensure_grub_boots_same_kernel(void);
>  
>  #endif /* IGT_PM_H */
> -- 
> 2.45.2
> 

  reply	other threads:[~2024-12-05 21:50 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-03  9:24 [PATCH i-g-t 0/2] Add hibernate helpers and kms_ccs hibernate test Juha-Pekka Heikkila
2024-12-03  9:24 ` [PATCH i-g-t 1/2] lib/igt_pm: Add helpers for hibernating kernel Juha-Pekka Heikkila
2024-12-05 21:49   ` Rodrigo Vivi [this message]
2024-12-03  9:24 ` [PATCH i-g-t 2/2] tests/intel/kms_ccs: add hiberbate test Juha-Pekka Heikkila
2024-12-05 21:52   ` Rodrigo Vivi
2024-12-03 13:41 ` ✗ i915.CI.BAT: failure for Add hibernate helpers and kms_ccs hibernate test Patchwork
2024-12-03 14:26 ` ✓ Xe.CI.BAT: success " Patchwork
2024-12-03 15:32 ` ✗ Xe.CI.Full: failure " Patchwork
2024-12-03 19:41 ` ✓ i915.CI.BAT: success for Add hibernate helpers and kms_ccs hibernate test (rev2) Patchwork
2024-12-03 19:52 ` ✗ Xe.CI.BAT: failure " Patchwork
2024-12-03 20:57 ` ✗ i915.CI.Full: " Patchwork
2024-12-03 21:05 ` ✗ Xe.CI.Full: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Z1IgBqtKWdkMycN-@intel.com \
    --to=rodrigo.vivi@intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=juhapekka.heikkila@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.