2 * (C) Copyright 2007-2010 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
13 static void *alloc_table(int order
)
17 p
= alloc_pages(order
, ZONE_NORMAL
);
19 memset(page_to_addr(p
), 0xff, PAGE_SIZE
<< order
);
21 return page_to_addr(p
);
25 * dat_insert_page - insert a virt->phy mapping into an address space
26 * @as: address space to add the mapping to
27 * @phy: physical address to add
28 * @virt: virtual address to add
30 int dat_insert_page(struct address_space
*as
, u64 phy
, u64 virt
)
32 struct dat_rte
*region
;
33 struct dat_ste
*segment
;
37 region
= as
->region_table
;
40 if (!as
->segment_table
)
42 * Need to allocate the segment table
44 * max of 2048 * 8-byte entries = 16 kbytes
46 as
->segment_table
= alloc_table(2);
48 segment
= as
->segment_table
;
54 FIXME("we don't support storage >2GB");
58 if (region
->origin
== 0xfffffffffffffUL
) {
60 * Need to allocate the segment table
62 * max of 2048 * 8-byte entries = 16 kbytes
66 region
->origin
= ADDR_TO_RTE_ORIGIN((u64
) ptr
);
70 region
->tt
= DAT_RTE_TT_RTT
;
72 region
->__reserved0
= 0;
73 region
->__reserved1
= 0;
76 segment
= RTE_ORIGIN_TO_ADDR(region
->origin
);
79 segment
+= DAT_SX(virt
);
81 if (segment
->origin
== 0x1fffffffffffffUL
) {
83 * Need to allocate the page table
85 * max of 256 * 8-byte entries = 2048 bytes
89 segment
->origin
= ADDR_TO_STE_ORIGIN((u64
) ptr
);
93 segment
->tt
= DAT_STE_TT_ST
;
94 segment
->__reserved0
= 0;
95 segment
->__reserved1
= 0;
96 segment
->__reserved2
= 0;
99 page
= STE_ORIGIN_TO_ADDR(segment
->origin
);
100 page
+= DAT_PX(virt
);
102 page
->pfra
= phy
>> PAGE_SHIFT
;
107 page
->__reserved
= 0;
117 void load_as(struct address_space
*as
)
121 BUG_ON(!as
->segment_table
);
124 * Load up the PASCE (cr1)
126 memset(&cr1
, 0, sizeof(struct dat_td
));
127 cr1
.origin
= ((u64
)as
->segment_table
) >> 12;
128 cr1
.dt
= DAT_TD_DT_ST
;
139 /* memcpy that pays attention to page boundary crossing; *len contains the
140 * number of bytes to copy on entry, and at return, the number of bytes
142 int __memcpy_tofrom_guest(u64 guest_addr
, void *data
, u64
*len
, int from
)
150 for(copied
= 0; *len
; ) {
151 /* walk the page tables to find the real page frame */
152 ret
= virt2phy_current(guest_addr
, &host_addr
);
156 /* copy this much this time around... until the end of the page, or
157 * the while thing that's left
159 copy_len
= min(PAGE_SIZE
- (host_addr
& PAGE_MASK
), *len
);
163 memcpy(_data
+ copied
, (void*)host_addr
, copy_len
);
165 memcpy((void*)host_addr
, _data
+ copied
, copy_len
);