|
|
1.1 root 1: /*
2: * Copyright (C) 2006-2009 Free Software Foundation
3: *
4: * This program is free software ; you can redistribute it and/or modify
5: * it under the terms of the GNU General Public License as published by
6: * the Free Software Foundation ; either version 2 of the License, or
7: * (at your option) any later version.
8: *
9: * This program is distributed in the hope that it will be useful,
10: * but WITHOUT ANY WARRANTY ; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: * GNU General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with the program ; if not, write to the Free Software
16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: */
18:
19: #include <sys/types.h>
20: #include <mach/vm_param.h>
21: #include <machine/spl.h>
22: #include <vm/pmap.h>
23: #include <vm/vm_map.h>
24: #include <vm/vm_kern.h>
25: #include "grant.h"
26:
27: #define NR_RESERVED_ENTRIES 8
28: #define NR_GRANT_PAGES 4
29:
30: decl_simple_lock_data(static,lock);
31: static struct grant_entry *grants;
32: static vm_map_entry_t grants_map_entry;
33: static int last_grant = NR_RESERVED_ENTRIES;
34:
35: static grant_ref_t free_grants = -1;
36:
37: static grant_ref_t grant_alloc(void) {
38: grant_ref_t grant;
39: if (free_grants != -1) {
40: grant = free_grants;
41: free_grants = grants[grant].frame;
42: } else {
43: grant = last_grant++;
44: if (grant == (NR_GRANT_PAGES * PAGE_SIZE)/sizeof(*grants))
45: panic("not enough grant entries, increase NR_GRANT_PAGES");
46: }
47: return grant;
48: }
49:
50: static void grant_free(grant_ref_t grant) {
51: grants[grant].frame = free_grants;
52: free_grants = grant;
53: }
54:
55: static grant_ref_t grant_set(domid_t domid, unsigned long mfn, uint16_t flags) {
56: spl_t spl = splhigh();
57: simple_lock(&lock);
58:
59: grant_ref_t grant = grant_alloc();
60: grants[grant].domid = domid;
61: grants[grant].frame = mfn;
62: wmb();
63: grants[grant].flags = flags;
64:
65: simple_unlock(&lock);
66: splx(spl);
67: return grant;
68: }
69:
70: grant_ref_t hyp_grant_give(domid_t domid, unsigned long frame, int readonly) {
71: return grant_set(domid, pfn_to_mfn(frame),
72: GTF_permit_access | (readonly ? GTF_readonly : 0));
73: }
74:
75: grant_ref_t hyp_grant_accept_transfer(domid_t domid, unsigned long frame) {
76: return grant_set(domid, frame, GTF_accept_transfer);
77: }
78:
79: unsigned long hyp_grant_finish_transfer(grant_ref_t grant) {
80: unsigned long frame;
81: spl_t spl = splhigh();
82: simple_lock(&lock);
83:
84: if (!(grants[grant].flags & GTF_transfer_committed))
85: panic("grant transfer %x not committed\n", grant);
86: while (!(grants[grant].flags & GTF_transfer_completed))
87: machine_relax();
88: rmb();
89: frame = grants[grant].frame;
90: grant_free(grant);
91:
92: simple_unlock(&lock);
93: splx(spl);
94: return frame;
95: }
96:
97: void hyp_grant_takeback(grant_ref_t grant) {
98: spl_t spl = splhigh();
99: simple_lock(&lock);
100:
101: if (grants[grant].flags & (GTF_reading|GTF_writing))
102: panic("grant %d still in use (%lx)\n", grant, grants[grant].flags);
103:
104: /* Note: this is not safe, a cmpxchg is needed, see grant_table.h */
105: grants[grant].flags = 0;
106: wmb();
107:
108: grant_free(grant);
109:
110: simple_unlock(&lock);
111: splx(spl);
112: }
113:
114: void *hyp_grant_address(grant_ref_t grant) {
115: return &grants[grant];
116: }
117:
118: void hyp_grant_init(void) {
119: struct gnttab_setup_table setup;
120: unsigned long frame[NR_GRANT_PAGES];
121: long ret;
122: int i;
123: vm_offset_t addr;
124:
125: setup.dom = DOMID_SELF;
126: setup.nr_frames = NR_GRANT_PAGES;
127: setup.frame_list = (void*) kvtolin(frame);
128:
129: ret = hyp_grant_table_op(GNTTABOP_setup_table, kvtolin(&setup), 1);
130: if (ret)
131: panic("setup grant table error %d", ret);
132: if (setup.status)
133: panic("setup grant table: %d\n", setup.status);
134:
135: simple_lock_init(&lock);
136: vm_map_find_entry(kernel_map, &addr, NR_GRANT_PAGES * PAGE_SIZE,
137: (vm_offset_t) 0, kernel_object, &grants_map_entry);
138: grants = (void*) addr;
139:
140: for (i = 0; i < NR_GRANT_PAGES; i++)
141: pmap_map_mfn((void *)grants + i * PAGE_SIZE, frame[i]);
142: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.