9 #define KMSG_COMPONENT "extmem"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12 #include <linux/kernel.h>
13 #include <linux/string.h>
15 #include <linux/list.h>
16 #include <linux/slab.h>
17 #include <linux/module.h>
19 #include <linux/ctype.h>
22 #include <asm/pgtable.h>
24 #include <asm/errno.h>
27 #include <asm/setup.h>
29 #define DCSS_LOADSHR 0x00
30 #define DCSS_LOADNSR 0x04
31 #define DCSS_PURGESEG 0x08
32 #define DCSS_FINDSEG 0x0c
33 #define DCSS_LOADNOLY 0x10
34 #define DCSS_SEGEXT 0x18
35 #define DCSS_LOADSHRX 0x20
36 #define DCSS_LOADNSRX 0x24
37 #define DCSS_FINDSEGX 0x2c
38 #define DCSS_SEGEXTX 0x38
39 #define DCSS_FINDSEGA 0x0c
66 struct qrange_old
range[6];
96 static char *segtype_string[] = {
"SW",
"EW",
"SR",
"ER",
"SN",
"EN",
"SC",
98 static int loadshr_scode, loadnsr_scode, findseg_scode;
99 static int segext_scode, purgeseg_scode;
100 static int scode_set;
104 dcss_set_subcodes(
void)
108 unsigned long rx,
ry;
114 rx = (
unsigned long) name;
126 :
"+d" (rx),
"+d" (ry),
"=d" (rc) : :
"cc");
153 dcss_mkname(
char *name,
char *dcss_name)
157 for (i = 0; i < 8; i++) {
173 segment_by_name (
char *name)
179 BUG_ON(!mutex_is_locked(&dcss_lock));
180 dcss_mkname (name, dcss_name);
196 dcss_diag(
int *
func,
void *parameter,
197 unsigned long *ret1,
unsigned long *ret2)
199 unsigned long rx,
ry;
202 if (scode_set == 0) {
203 rc = dcss_set_subcodes();
208 rx = (
unsigned long) parameter;
209 ry = (
unsigned long) *func;
218 :
"+d" (
rx),
"+d" (ry),
"=d" (
rc) : :
"cc");
227 :
"+d" (
rx),
"+d" (ry),
"=d" (
rc) : :
"cc");
233 :
"+d" (
rx),
"+d" (ry),
"=d" (
rc) : :
"cc");
241 dcss_diag_translate_rc (
int vm_rc) {
254 unsigned long dummy, vmrc;
261 if ((qin ==
NULL) || (qout ==
NULL)) {
272 diag_cc = dcss_diag(&segext_scode, qin, &dummy, &vmrc);
279 pr_warning(
"Querying a DCSS type failed with rc=%ld\n", vmrc);
280 rc = dcss_diag_translate_rc (vmrc);
288 struct qout64_old *qout_old;
290 if (qout_old ==
NULL) {
294 memcpy(qout_old, qout,
sizeof(
struct qout64_old));
296 qout->
segend = (
unsigned long) qout_old->segend;
297 qout->
segcnt = qout_old->segcnt;
298 qout->
segrcnt = qout_old->segrcnt;
302 for (i = 0; i < qout->
segrcnt; i++) {
304 (
unsigned long) qout_old->range[i].start;
306 (
unsigned long) qout_old->range[
i].end;
324 for (i=0; i<qout->
segcnt; i++) {
374 rc = query_segment_type (&seg);
390 BUG_ON(!mutex_is_locked(&dcss_lock));
414 start_addr = end_addr = 0;
421 rc = query_segment_type (seg);
426 if (segment_overlaps_others(seg)) {
461 diag_cc = dcss_diag(&loadnsr_scode, seg->
dcss_name,
462 &start_addr, &end_addr);
464 diag_cc = dcss_diag(&loadshr_scode, seg->
dcss_name,
465 &start_addr, &end_addr);
467 dcss_diag(&purgeseg_scode, seg->
dcss_name,
473 pr_warning(
"Loading DCSS %s failed with rc=%ld\n", name,
475 rc = dcss_diag_translate_rc(end_addr);
476 dcss_diag(&purgeseg_scode, seg->
dcss_name,
484 list_add(&seg->
list, &dcss_list);
488 pr_info(
"DCSS %s of range %p to %p and type %s loaded as "
489 "exclusive-writable\n", name, (
void*) seg->
start_addr,
492 pr_info(
"DCSS %s of range %p to %p and type %s loaded in "
493 "shared access mode\n", name, (
void*) seg->
start_addr,
538 seg = segment_by_name (name);
540 rc = __segment_load (name, do_nonshared, addr, end);
576 start_addr = end_addr = 0;
578 seg = segment_by_name (name);
584 pr_info(
"DCSS %s is already in the requested access "
590 pr_warning(
"DCSS %s is in use and cannot be reloaded\n",
604 pr_warning(
"DCSS %s overlaps with used memory resources "
605 "and cannot be reloaded\n", name);
611 dcss_diag(&purgeseg_scode, seg->
dcss_name, &dummy, &dummy);
613 diag_cc = dcss_diag(&loadnsr_scode, seg->
dcss_name,
614 &start_addr, &end_addr);
616 diag_cc = dcss_diag(&loadshr_scode, seg->
dcss_name,
617 &start_addr, &end_addr);
623 pr_warning(
"Reloading DCSS %s failed with rc=%ld\n", name,
625 rc = dcss_diag_translate_rc(end_addr);
639 dcss_diag(&purgeseg_scode, seg->
dcss_name, &dummy, &dummy);
661 seg = segment_by_name (name);
663 pr_err(
"Unloading unknown DCSS %s failed\n", name);
672 dcss_diag(&purgeseg_scode, seg->
dcss_name, &dummy, &dummy);
693 seg = segment_by_name (name);
696 pr_err(
"Saving unknown DCSS %s failed\n", name);
700 sprintf(cmd1,
"DEFSEG %s", name);
701 for (i=0; i<seg->
segcnt; i++) {
705 segtype_string[seg->
range[i].start & 0xff]);
707 sprintf(cmd2,
"SAVESEG %s", name);
711 pr_err(
"Saving a DCSS failed with DEFSEG response code "
717 pr_err(
"Saving a DCSS failed with SAVESEG response code "
733 pr_err(
"DCSS %s cannot be loaded or queried\n", seg_name);
736 pr_err(
"DCSS %s cannot be loaded or queried without "
740 pr_err(
"Loading or querying DCSS %s resulted in a "
741 "hardware error\n", seg_name);
744 pr_err(
"DCSS %s has multiple page ranges and cannot be "
745 "loaded or queried\n", seg_name);
748 pr_err(
"DCSS %s overlaps with used storage and cannot "
749 "be loaded\n", seg_name);
752 pr_err(
"%s needs used memory resources and cannot be "
753 "loaded or queried\n", seg_name);
756 pr_err(
"DCSS %s is already loaded in a different access "
760 pr_err(
"There is not enough memory to load or query "
761 "DCSS %s\n", seg_name);
764 pr_err(
"DCSS %s exceeds the kernel mapping range (%lu) "