1 /* $OpenBSD: hibernate_machdep.c,v 1.8 2015/05/05 02:13:46 guenther Exp $ */
2
3 /*
4 * Copyright (c) 2013 Paul Irofti.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19
20 #include <sys/param.h>
21 #include <sys/buf.h>
22 #include <sys/conf.h>
23 #include <sys/device.h>
24 #include <sys/disk.h>
25 #include <sys/disklabel.h>
26 #include <sys/hibernate.h>
27 #include <sys/timeout.h>
28 #include <sys/malloc.h>
29
30 #include <uvm/uvm_extern.h>
31 #include <uvm/uvm_pmemrange.h>
32
33 #include <mips64/cache.h>
34
35 #include <machine/hibernate.h>
36 #include <machine/hibernate_var.h>
37 #include <machine/kcore.h>
38 #include <machine/pmap.h>
39 #include <machine/memconf.h>
40
41 #include "wd.h"
42 #include "ahci.h"
43 #include "softraid.h"
44 #include "sd.h"
45
46 #if NWD > 0
47 #include <dev/ata/atavar.h>
48 #include <dev/ata/wdvar.h>
49 #endif
50
51 /*
52 * Loongson MD Hibernate functions
53 *
54 * see Loongson hibernate.h for lowmem layout used during hibernate
55 */
56
57 /*
58 * Returns the hibernate write I/O function to use on this machine
59 */
60 hibio_fn
get_hibernate_io_function(dev_t dev)61 get_hibernate_io_function(dev_t dev)
62 {
63 char *blkname = findblkname(major(dev));
64
65 if (blkname == NULL)
66 return NULL;
67
68 #if NWD > 0
69 if (strcmp(blkname, "wd") == 0)
70 return wd_hibernate_io;
71 #endif
72 #if NSD > 0
73 if (strcmp(blkname, "sd") == 0) {
74 extern struct cfdriver sd_cd;
75 extern int ahci_hibernate_io(dev_t dev, daddr_t blkno,
76 vaddr_t addr, size_t size, int op, void *page);
77 extern int sr_hibernate_io(dev_t dev, daddr_t blkno,
78 vaddr_t addr, size_t size, int op, void *page);
79 struct device *dv = disk_lookup(&sd_cd, DISKUNIT(dev));
80
81 #if NAHCI > 0
82 if (dv && dv->dv_parent && dv->dv_parent->dv_parent &&
83 strcmp(dv->dv_parent->dv_parent->dv_cfdata->cf_driver->cd_name,
84 "ahci") == 0)
85 return ahci_hibernate_io;
86 #endif
87 #if NSOFTRAID > 0
88 if (dv && dv->dv_parent && dv->dv_parent->dv_parent &&
89 strcmp(dv->dv_parent->dv_parent->dv_cfdata->cf_driver->cd_name,
90 "softraid") == 0)
91 return sr_hibernate_io;
92 }
93 #endif
94 #endif /* NSD > 0 */
95 return NULL;
96 }
97
98 /*
99 * Gather MD-specific data and store into hiber_info
100 */
101 int
get_hibernate_info_md(union hibernate_info * hiber_info)102 get_hibernate_info_md(union hibernate_info *hiber_info)
103 {
104 int i;
105
106 /* Calculate memory ranges */
107 hiber_info->nranges = 0;
108 hiber_info->image_size = 0;
109
110 for (i = 0; i < MAXMEMSEGS && mem_layout[i].mem_last_page != 0; i++) {
111 /* XXX: Adjust for stolen pages later */
112 hiber_info->ranges[i].base =
113 mem_layout[i].mem_first_page >> PAGE_SHIFT;
114 hiber_info->ranges[i].end =
115 mem_layout[i].mem_last_page >> PAGE_SHIFT;
116 hiber_info->image_size +=
117 hiber_info->ranges[i].end - hiber_info->ranges[i].base;
118 hiber_info->nranges++;
119 }
120
121 return (0);
122 }
123
124 /*
125 * Enter a mapping for va->pa in the resume pagetable
126 */
127 void
hibernate_enter_resume_mapping(vaddr_t va,paddr_t pa,int size)128 hibernate_enter_resume_mapping(vaddr_t va, paddr_t pa, int size)
129 {
130 /* XXX TBD */
131 }
132
133 /*
134 * Create the resume-time page table. This table maps the image(pig) area,
135 * the kernel text area, and various utility pages for use during resume,
136 * since we cannot overwrite the resuming kernel's page table during inflate
137 * and expect things to work properly.
138 */
139 void
hibernate_populate_resume_pt(union hibernate_info * hib_info,paddr_t image_start,paddr_t image_end)140 hibernate_populate_resume_pt(union hibernate_info *hib_info,
141 paddr_t image_start, paddr_t image_end)
142 {
143 /* XXX TBD */
144 }
145
146 /*
147 * During inflate, certain pages that contain our bookkeeping information
148 * (eg, the chunk table, scratch pages, etc) need to be skipped over and
149 * not inflated into.
150 *
151 * Returns 1 if the physical page at dest should be skipped, 0 otherwise
152 */
153 int
hibernate_inflate_skip(union hibernate_info * hib_info,paddr_t dest)154 hibernate_inflate_skip(union hibernate_info *hib_info, paddr_t dest)
155 {
156 if (dest >= hib_info->piglet_pa &&
157 dest <= (hib_info->piglet_pa + 4 * HIBERNATE_CHUNK_SIZE))
158 return (1);
159
160 return (0);
161 }
162
163 void
hibernate_enable_intr_machdep(void)164 hibernate_enable_intr_machdep(void)
165 {
166 enableintr();
167 }
168
169 void
hibernate_disable_intr_machdep(void)170 hibernate_disable_intr_machdep(void)
171 {
172 disableintr();
173 }
174
175 void
hibernate_flush(void)176 hibernate_flush(void)
177 {
178 Mips_SyncCache(curcpu());
179 }
180